Невозможно преобразовать типы данных при циклическом просмотре списка словарей

#python #python-3.x

#python #python-3.x

Вопрос:

Я пытаюсь выполнить цикл по списку словарей и преобразовать их тип данных на основе ссылки на другой конфигурационный словарь, который содержит типы данных, в которые я хочу преобразовать.

Конфигурационный словарь следующий:

 search_results_config = {

    'id':'int',
    'description':'string',
    'page':'int',
    'position':'int',
    'title':'string',
    'type':'int',
    'typedescription':'string',
    'url':'string'
}
  

И список словарей, которые я на самом деле пытаюсь просмотреть top_rank_data и изменить типы данных, выглядит следующим образом:

  {
        'description': 'Churchill contents insurance covers the things that matter most in your home. We offer cover of up to £50,000 asxa0',
        'position': 18, 'page': 2, 'title': 'Contents insurance | Home Insurance | Churchill UK', 'type': '0',
        'typedescription': 'organic', 'url': 'https://www.churchill.com/home-insurance/options/contents'}, {
        'description': 'Compare contents insurance and how to cut the cost of home contents insurance cover for your personal possessionsxa0',
        'position': 19, 'page': 2, 'title': 'Contents Insurance - compare cheap contents insurance', 'type': '0',
        'typedescription': 'organic', 'url': 'https://www.uswitch.com/home-insurance/contents-insurance/'}

  

Приведенный ниже код:

 for row in top_rank_data:

    for item in row:

        for key, value in search_results_config.items():
            new_value = None
            config_type = search_results_config[key]

        if config_type == 'string':
            new_value = str(value) or ''

        if config_type == 'int':
            new_value = int(value) or 9
  

Поэтому я ожидаю, что значение любого ключа изменит тип данных в соответствии со search_results_config словарем. Вместо этого я возвращаю только string тип данных для всех, поэтому я предполагаю, что if config_type инструкции не работают. Любая помощь очень ценится!

Дополнительная функция, генерирующая данные:

 path = 'C:downloaded'
for filename in glob.glob(os.path.join(path, '*.json')):
    with open(filename, encoding='utf-8', mode='r') as currentFile:
        data = currentFile.read()
        rank_data = json.loads(data)["rankdata"]

        for entry in rank_data:
            if (entry["page"]) <= 2 and (entry["typedescription"]) == "organic":
                top_rank_data.append(entry)
  

Ответ №1:

это версия для этого:

 search_results_config = {

    'id': int,
    'description': str,
    'page': int,
    'position': int,
    'title': str,
    'type': int,
    'typedescription': str,
    'url': str
}

items = ({
        'description': 'Churchill contents insurance covers the things that matter most in your home. We offer cover of up to £50,000 asxa0',
        'position': 18, 'page': 2, 'title': 'Contents insurance | Home Insurance | Churchill UK', 'type': '0',
        'typedescription': 'organic', 'url': 'https://www.churchill.com/home-insurance/options/contents'}, {
        'description': 'Compare contents insurance and how to cut the cost of home contents insurance cover for your personal possessionsxa0',
        'position': 19, 'page': 2, 'title': 'Contents Insurance - compare cheap contents insurance', 'type': '0',
        'typedescription': 'organic', 'url': 'https://www.uswitch.com/home-insurance/contents-insurance/'})

def convert(dct):
    return {key: search_results_config[key](value) for key, value in dct.items()}


for dct in items:
    print(convert(dct))
  

обратите внимание, что search_results_config непосредственно содержит типы (т. Е. int вместо 'int' ), которые используются для преобразования ваших данных.


вы также можете добавить тип по умолчанию (который я использовал str в примере ниже) для key типов, которые не существуют в search_results_config :

 def convert(dct):
    return {key: search_results_config.get(key, str)(value) 
            for key, value in dct.items()}
  

Комментарии:

1. Спасибо, это работает! Единственная проблема в том, что когда я пытаюсь использовать все исходные данные, я получаю сообщение об ошибке Type = search_results_config[key] KeyError: 'snippets' Я добавил функцию, которая генерирует данные в конце вопроса, чтобы посмотреть, видно ли здесь что-нибудь, что может быть причиной этого?

2. Есть ли способ добавить обработку отсутствующих значений в соответствии с исходным примером? Итак, в случае string, если значение отсутствует, добавляется пробел, а в случае int добавляется 9 в качестве значения по умолчанию?

3. вместо «стандартного» конвертера (т. Е. int ) вы всегда можете определить свой собственный конвертер def to_my_int(value): return int(value) or 9 и добавить to_my_int в словарь для рассматриваемого поля.

Ответ №2:

Попробуйте этот подход:

 New_List = []
for dictionary in top_rank_data:
    Sub_Dict = {}
    for key, value in dictionary.items():
        Type = search_results_config[key]
        try:
            New_Val = Type(value)
        except:
            New_Val = value

        Sub_Dict[key] = New_Val

    New_List.append(Sub_Dict)