Как объединить список из нескольких словарей в словарь списков? - PullRequest
0 голосов
/ 08 октября 2018

У меня есть следующий список словарей в Python3.x:

list_of_dictionaries = [{0:3523, 1:3524, 2:3540, 4:3541, 5:3542}, 
                        {0:7245, 1:7246, 2:7247, 3:7248, 5:7249, 6:7250},
                        {1:20898, 2:20899, 3:20900, 4:20901, 5:20902}]

В данном случае это один список с тремя словарями.

Я хотел бы эффективно объединить это в один словарь со списками в качестве значений;вот правильный ответ:

correct = {0:[3523, 7245], 1:[3524, 7246, 20898], 2:[3540, 7247, 20899], 
               3:[7248, 20900], 4:[3541, 20901], 5:[3542, 7249, 20902], 6:[7250]}

Моей первой мыслью было понимание списка следующим образом:

dict(pair for dictionary in list_of_dictionaries for pair in dictionary.items())

Но это неправильно, так как не включает списки значений:

{0: 7245, 1: 20898, 2: 20899, 4: 20901, 5: 20902, 3: 20900, 6: 7250}

Я также беспокоюсь о том, как максимально эффективно создавать списки значений.Он также может не масштабироваться до больших списков / больших словарей.

Как мне это сделать?

Ответы [ 4 ]

0 голосов
/ 08 октября 2018

Используя groupby и itemgetter , мы могли бы сначала создать плоский список кортежей, которые представляют keys and values каждого поддикта.Тогда мы можем использовать groupby в нашем отсортированном новом списке.Оттуда мы можем создать наш новый словарь, используя k и элементы в index[1] из list(g)

from itertools import groupby
from operator import itemgetter

d = {}
new_lod = sorted([(j, i[j]) for i in lod for j in i], key=itemgetter(0))
for k, g in groupby(new_lod, key=itemgetter(0)):
    d[k] = [i[1] for i in list(g)]

# {0: [3523, 7245], 1: [3524, 7246, 20898], 2: [3540, 7247, 20899], 3: [7248, 20900], 4: [3541, 20901], 5: [3542, 7249, 20902], 6: [7250]}
0 голосов
/ 08 октября 2018

Сначала необходимо сгладить словари:

flattened_pairs = (
    pair for dictionary in list_of_dictionaries for pair in dictionary.items()
)

Затем вы можете использовать itertools.groupby для группировки значений.Ожидается, что значения будут отсортированы по ключу.

key_fn = lambda pair: pair[0]

merged = {
    k: [pair[1] for pair in g]
    for k, g in groupby(
        sorted(flattened_pairs, key=key_fn),
        key=key_fn
    )
}

print(merged)

Вывод:

{0: [3523, 7245], 1: [3524, 7246, 20898], 2: [3540, 7247, 20899], 3: [7248, 20900], 4: [3541, 20901], 5: [3542, 7249, 20902], 6: [7250]}

0 голосов
/ 08 октября 2018

почему бы просто не использовать for петли?например:

final = {}

for i in list_of_dictionaries:
    for k in i:
        if not k in final:
            final[k] = []
        final[k].append(i[k])


print(final)

Окончательные выходы как:

{0: [3523, 7245], 1: [3524, 7246, 20898], 2: [3540, 7247, 20899], 4: [3541, 20901], 5: [3542, 7249, 20902], 3: [7248, 20900], 6: [7250]}

0 голосов
/ 08 октября 2018

defaultdict

Вы можете использовать collections.defaultdict.Ваше понимание словаря никогда не будет работать, так как вы не определяете никаких списков.Это, вероятно, будет более эффективным, чем использование словарного понимания, которое будет включать итерацию каждого словаря для каждого уникального ключа.

from collections import defaultdict

dd = defaultdict(list)

for d in list_of_dictionaries:
    for k, v in d.items():
        dd[k].append(v)

Результат:

print(dd)

defaultdict(list,
            {0: [3523, 7245],
             1: [3524, 7246, 20898],
             2: [3540, 7247, 20899],
             4: [3541, 20901],
             5: [3542, 7249, 20902],
             3: [7248, 20900],
             6: [7250]})

Понимание словаря

Понимание словаря возможно , но для этого требуется вычислить объединение ключей и выполнить итерацию списка словарей для каждого из этих ключей:

allkeys = set().union(*list_of_dictionaries)

res = {k: [d[k] for d in list_of_dictionaries if k in d] for k in allkeys}

{0: [3523, 7245],
 1: [3524, 7246, 20898],
 2: [3540, 7247, 20899],
 3: [7248, 20900],
 4: [3541, 20901],
 5: [3542, 7249, 20902],
 6: [7250]}

Сложность времени

Рассмотрим следующие термины:

n = sum(map(len, list_of_dictionaries))
m = len(set().union(*list_of_dictionaries))
k = len(list_of_dictionaries)

В этом контексте решение defaultdict будет иметь сложность O ( n ), тогда как понимание словаря будет иметь сложность O ( mk *)1027 *), где мк > = n .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...