Объединить 2 списка словарей на основе совпадающих значений, в противном случае оставить оригинал? - PullRequest
0 голосов
/ 11 мая 2018

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

Желаемый вывод:

combined = [
    {'Type':'Tree', 'Name':'Pear', 'Color':'Red,Green', 'Height':'25ft'},
    {'Type':'Bush', 'Name':'Raspberry', 'Color':'Red,White'},
    {'Type':'Tree', 'Name':'Apple', 'Color':'Red,Green', 'Height':'15ft'}
]

Стартовые таблицы:

fruit = [
    {'Type':'Tree', 'Name':'Pear', 'Color':'Red,Green'},
    {'Type':'Bush', 'Name':'Raspberry', 'Color':'Red,White'},
    {'Type':'Tree', 'Name':'Apple', 'Color':'Red,Green'}
]

type = [
    {'Type':'Tree', 'Fruit':'Pear', 'Height':'25ft'},
    {'Type':'Tree', 'Fruit':'Apple', 'Height':'15ft'},
    {'Type':'Root', 'Fruit':'Carrot', 'Height':'2ft'}
]

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

combined = []
for i in fruit:
    for x in type:
        if i['Name'] == x['Name']:
            out = i
            out['Height'] = x['Height']
            combined.append(out)
        else:
            combined.append(i)

Ответы [ 3 ]

0 голосов
/ 11 мая 2018

Проблема заключается в операторе if-else внутри вашего внутреннего цикла.

Вы должны установить флаг, чтобы проверить, есть ли совпадение внутри вашего внутреннего цикла, если его нет, вы должны добавить текущий фрукт за пределы внутреннего цикла.

combined = []
for i in fruit:
    found = False
    for x in type:
        if i['Name'] == x['Fruit']:
            out = []
            out = i
            out['Height'] = x['Height']
            combined.append(out)
            found = True
    if found == False:
        combined.append(i)
0 голосов
/ 11 мая 2018

Если вы используете Python 3.5+, используйте переменные fruit и tree_type, как вы определили (type был переименован в tree_type, чтобы избежать конфликта):

combined = [{**fruit_dict, 
             **next((type_dict for type_dict in tree_type if fruit_dict["Name"] == type_dict["Fruit"]), {})} 
            for fruit_dict in fruit]

Некоторое объяснение этого кода:

Выражение next((type_dict for type_dict in tree_type if fruit_dict["Name"] == type_dict["Fruit"]), {}) находит type_dict внутри tree_type, совпадающее с fruit_dict, и возвращает его, в противном случае возвращается пустой dict {}.

Выражение {**d1, **d2} используется для объединения двух словарей. Ни один из словарей не изменяется в этом выражении, возвращается новый.

Этот код не оптимизирован, если tree_type большой список. Если это так, вы должны организовать этот список в другую структуру данных, вероятно, словарь.

Например:

tree_types_by_fruit = {type_dict["Fruit"]: type_dict for type_dict in tree_type}
combined = [{**fruit_dict, **tree_types_by_fruit.get(fruit_dict["Name"], {})} for fruit_dict in fruit]
0 голосов
/ 11 мая 2018

Это один из способов избежать вложенного цикла for.

Настройка

fruit = [{'Type':'Tree', 'Name':'Pear', 'Color':'Red,Green'},
         {'Type':'Bush', 'Name':'Raspberry', 'Color':'Red,White'},
         {'Type':'Tree', 'Name':'Apple', 'Color':'Red,Green'}]

tree_types = [{'Type':'Tree', 'Fruit':'Pear', 'Height':'25ft'},
              {'Type':'Tree', 'Fruit':'Apple', 'Height':'15ft'},
              {'Type':'Root', 'Fruit':'Carrot', 'Height':'2ft'}]

Примечание: не называйте переменные после встроенных модулей, например, type.

Решение

tree_types_d = {(i['Type'], i['Fruit']): i['Height'] for i in tree_types}

for item in fruit:
    tup = (item['Type'], item['Name'])
    if tup in tree_types_d:
        item['Height'] = tree_types_d[tup]

Результат

[{'Color': 'Red,Green', 'Height': '25ft', 'Name': 'Pear', 'Type': 'Tree'},
 {'Color': 'Red,White', 'Name': 'Raspberry', 'Type': 'Bush'},
 {'Color': 'Red,Green', 'Height': '15ft', 'Name': 'Apple', 'Type': 'Tree'}]

Объяснение

  • Реструктурировать tree_types как словарь кортежей, tree_types_d.
  • Итерация fruit и добавление элемента Height, где есть совпадение, с tree_types_d.
  • Разовые затраты на создание нового словаря часто предпочтительнее вложенных циклов for.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...