在 Python 中组合列表字典

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1495510/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 22:24:55  来源:igfitidea点击:

Combining Dictionaries Of Lists In Python

pythonlistdictionary

提问by user108088

I have a very large collection of (p, q) tuples that I would like to convert into a dictionary of lists where the first item in each tuple is a key that indexes a list that contains q.

我有一个非常大的 (p, q) 元组集合,我想将它们转换为列表字典,其中每个元组中的第一项是索引包含 q 的列表的键。

Example:

例子:

Original List: (1, 2), (1, 3), (2, 3)  
Resultant Dictionary: {1:[2, 3], 2:[3]}  

Furthermore, I would like to efficiently combine these dictionaries.

此外,我想有效地组合这些词典。

Example:

例子:

Original Dictionaries: {1:[2, 3], 2:[3]}, {1:[4], 3:[1]}  
Resultant Dictionary: {1:[2, 3, 4], 2:[3], 3:[1]}  

These operations reside within an inner loop, so I would prefer that they be as fast as possible.

这些操作驻留在内部循环中,所以我希望它们尽可能快。

Thanks in advance

提前致谢

采纳答案by Alex Martelli

If the list of tuples is sorted, itertools.groupby, as suggested by @gnibbler, is not a bad alternative to defaultdict, but it needs to be used differently than he suggested:

如果元组列表已排序,itertools.groupby正如@gnibbler 所建议的那样, 不是一个糟糕的替代方案defaultdict,但它的使用方式需要与他建议的不同:

import itertools
import operator

def lot_to_dict(lot):
  key = operator.itemgetter(0)
  # if lot's not sorted, you also need...:
  # lot = sorted(lot, key=key)
  # NOT in-place lot.sort to avoid changing it!
  grob = itertools.groupby(lot, key)
  return dict((k, [v[1] for v in itr]) for k, itr in grob)

For "merging" dicts of lists into a new d.o.l...:

将列表的字典“合并”到一个新的 dol.. 中:

def merge_dols(dol1, dol2):
  keys = set(dol1).union(dol2)
  no = []
  return dict((k, dol1.get(k, no) + dol2.get(k, no)) for k in keys)

I'm giving []a nickname noto avoid uselessly constructing a lot of empty lists, given that performance is important. If the sets of the dols' keys overlap only modestly, faster would be:

鉴于性能很重要,我给出[]了一个昵称,no以避免无用地构建大量空列表。如果 dols 的密钥集仅适度重叠,则更快:

def merge_dols(dol1, dol2):
  result = dict(dol1, **dol2)
  result.update((k, dol1[k] + dol2[k])
                for k in set(dol1).intersection(dol2))
  return result

since this uses list-catenation only for overlapping keys -- so, if those are few, it will be faster.

因为这仅对重叠的键使用列表连接 - 所以,如果这些键很少,它会更快。

回答by SilentGhost

collections.defaultdictworks like this:

collections.defaultdict像这样工作:

from collections import defaultdict
dic = defaultdict(list)
for i, j in tuples:
    dic[i].append(j)

similar for the dicts:

类似于 dicts:

a, b = {1:[2, 3], 2:[3]}, {1:[4], 3:[1]}
de = defaultdict(list, a)
for i, j in b.items():
    de[i].extend(j)

回答by Triptych

defaltdict to the rescue (as usual)

defaltdict 救援(像往常一样)

from collections import defaultdict
my_dict = defaultdict(list)

for key,value in original_list:
    my_dict[key].append(value)

Combining the two dicts can be done like this (note that duplicates will be preserved):

可以像这样组合两个字典(注意重复项将被保留):

for key,value in orig_dict:
    new_dict[key].extend(value)

回答by John La Rooy

Here is the iterator style of doing it

这是这样做的迭代器风格

>>> mylist=[(1, 2), (1, 3), (2, 3)]
>>> from itertools import groupby
>>> from operator import itemgetter
>>> mylist=[(1, 2), (1, 3), (2, 3)]
>>> groupby(mylist,itemgetter(0))

>>> list(_)
[(1, <itertools._grouper object at 0xb7d402ec>), (2, <itertools._grouper object at 0xb7c716ec>)]

回答by Tarnay Kálmán

I wanted these done in one linejust for fun:

我希望这些在一行中完成只是为了好玩:

>>> from itertools import groupby
>>> t=(1, 2), (1, 3), (2, 3) 
>>> [(i,[x for _,x in list(f)]) for i,f in groupby(sorted(t),lambda t: t[0])] 
[(1, [2, 3]), (2, [3])]
>>> b={1:[2, 3], 2:[3]}, {1:[4], 3:[1]}
>>> dict([(key,sum([i[1::][0] for i in elements],[])) for key,elements in groupby(sorted(b[0].items()+b[1].items()),lambda t: t[0])])
{1: [2, 3, 4], 2: [3], 3: [1]}