Объединить / соединить списки словарей на основе общего значения в Python

У меня есть два списка словарей (возвращаемых в качестве запросов Django). Каждый словарь имеет значение ID. Я хотел бы объединить их в один список словарей, основанный на значении ID.

Например:

list_a = [{'user__name': u'Joe', 'user__id': 1}, {'user__name': u'Bob', 'user__id': 3}] list_b = [{'hours_worked': 25, 'user__id': 3}, {'hours_worked': 40, 'user__id': 1}] 

и я хочу получить функцию:

 list_c = [{'user__name': u'Joe', 'user__id': 1, 'hours_worked': 40}, {'user__name': u'Bob', 'user__id': 3, 'hours_worked': 25}] 

Дополнительные замечания:

  • Идентификаторы в списках могут быть не в том же порядке (как в примере выше).
  • В списках, вероятно, будет одинаковое количество элементов, но я хочу учесть эту опцию, если они не сохраняют все значения из list_a (по существу list_a OUTER JOIN list_b USING user__id ).
  • Я попытался сделать это в SQL, но это невозможно, поскольку некоторые из значений являются агрегатами на основе некоторых исключений.
  • Можно с уверенностью предположить, что в каждом списке будет использоваться не более одного словаря с одним и тем же user__id из-за использованных запросов к базе данных.

Большое спасибо за ваше время.

  • Получение сообщения о ходе выполнения из подпроцесса
  • Понимание Tkinter после ()
  • Как динамически загружать класс Python
  • Анализ аудио с использованием быстрого преобразования Фурье
  • отправить запрос с использованием python на страницу asp.net
  • Разница между Python datetime и модулями времени
  • OpenCV: преобразование из NumPy в IplImage в Python
  • Создавайте соединение с БД и поддерживайте несколько процессов (многопроцессорность)
  • 2 Solutions collect form web for “Объединить / соединить списки словарей на основе общего значения в Python”

    Я бы использовал itertools.groupby для группировки элементов:

     lst = sorted(itertools.chain(list_a,list_b), key=lambda x:x['user__id']) list_c = [] for k,v in itertools.groupby(lst, key=lambda x:x['user__id']): d = {} for dct in v: d.update(dct) list_c.append(d) #could also do: #list_c.append( dict(itertools.chain.from_iterable(dct.items() for dct in v)) ) #although that might be a little harder to read. 

    Если у вас есть отвращение к lambda функциям, вы всегда можете использовать operator.itemgetter('user__id') . (это, вероятно, немного более эффективно)

    Чтобы немного демистифицировать лямбда / itemgetter, обратите внимание, что:

     def foo(x): return x['user__id'] 

    это то же самое *, что и одно из следующего:

     foo = operator.itemgetter('user__id') foo = lambda x: x['user__id'] 

    * Есть несколько отличий, но они не важны для этой проблемы.

     from collections import defaultdict from itertools import chain list_a = [{'user__name': u'Joe', 'user__id': 1}, {'user__name': u'Bob', 'user__id': 3}] list_b = [{'hours_worked': 25, 'user__id': 3}, {'hours_worked': 40, 'user__id': 1}] collector = defaultdict(dict) for collectible in chain(list_a, list_b): collector[collectible['user__id']].update(collectible.iteritems()) list_c = list(collector.itervalues()) 

    Как вы можете видеть, это просто использует другой dict, чтобы объединить существующие dicts. Трюк с defaultdict заключается в том, что он извлекает трудность создания dict для новой записи.

    Нет необходимости группировать или сортировать эти входы. Этот дикт заботится обо всем этом.

    Поистине пуленепробиваемое решение поймало бы потенциальную ключевую ошибку, если вход не имеет ключа «user__id» или использует значение по умолчанию для сбора всех данных без такого ключа.

    Python - лучший язык программирования в мире.