在python中合并字典值列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26910708/
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
Merging dictionary value lists in python
提问by branwen85
I'm trying to merge three dictionaries, which all have the same keys, and either lists of values, or single values.
我正在尝试合并三个字典,它们都具有相同的键,以及值列表或单个值。
one={'a': [1, 2], 'c': [5, 6], 'b': [3, 4]}
two={'a': [2.4, 3.4], 'c': [5.6, 7.6], 'b': [3.5, 4.5]}
three={'a': 1.2, 'c': 3.4, 'b': 2.3}
What I need is for all the items in the values to be added to one list.
我需要的是将值中的所有项目添加到一个列表中。
result={'a': [1, 2, 2.4, 3.4, 1.2], 'c': [5, 6, 5.6, 7.6, 2.3], 'b': [3, 4, 3.5, 4.5, 3.4]}
I have tried several things, but most put the values into nested lists. E.g.
我尝试了几件事,但大多数都将值放入嵌套列表中。例如
out=dict((k, [one[k], two.get(k), three.get(k)]) for k in one)
{'a': [[1, 2], [2.4, 3.4], 1.2], 'c': [[5, 6], [5.6, 7.6], 3.4], 'b': [[3, 4], [3.5, 4.5], 2.3]}
I tried updating it by looping through the values:
我尝试通过遍历值来更新它:
out.update((k, [x for x in v]) for k,v in out.iteritems())
but the results was exactly the same. I have tried to simply add the lists, but because the third dictionary has only a float, I couldn't do it.
但结果完全一样。我试图简单地添加列表,但因为第三个字典只有一个浮点数,我不能这样做。
check=dict((k, [one[k]+two[k]+three[k]]) for k in one)
So I tried to first add the lists in values of one and two, and then append the value of three. Adding the lists worked well, but then when I tried to append the float from the third dictionary, suddenly the whole value went to 'None'
所以我尝试首先添加值一和二的列表,然后附加值三。添加列表效果很好,但是当我尝试从第三个字典中附加浮点数时,突然整个值变为“无”
check=dict((k, [one[k]+two[k]]) for k in one)
{'a': [[1, 2, 2.4, 3.4]], 'c': [[5, 6, 5.6, 7.6]], 'b': [[3, 4, 3.5, 4.5]]}
new=dict((k, v.append(three[k])) for k,v in check.items())
{'a': None, 'c': None, 'b': None}
采纳答案by Martijn Pieters
As a one-liner, with a dictionary comprehension:
作为单行,用字典理解:
new = {key: value + two[key] + [three[key]] for key, value in one.iteritems()}
This creates new lists, concatenating the list from onewith the corresponding list from two, putting the single value in threeinto a temporary list to make concatenating easier.
这将创建新列表,将列表 fromone与相应的列表 from 连接起来two,将单个值three放入临时列表中,使连接更容易。
Or with a forloop updating onein-place:
或者使用for循环更新one就地:
for key, value in one.iteritems():
value.extend(two[key])
value.append(three[key])
This uses list.extend()to update original list in-place with the list from two, and list.append()to add the single value from three.
这用于使用list.extend()来自 的列表就地更新原始列表two,并list.append()添加来自 的单个值three。
Where you went wrong:
你哪里出错了:
your first attempt creates a new list with the values from
one,twoandthreenested within rather than concatenating the existing lists. Your attempt to clean that up just copied those nested lists across.Your second attempt didn't work because the value in
threeis not a list so could not be concatenated. I created a new list just for that one value.Your last attempt should not have used
list.append()in a generator expression, because you store the return valueof that method, which is alwaysNone(its change is stored invdirectly and the list doesn't need returning again).
您的第一次尝试使用来自 的值创建一个新列表
one,two并three嵌套在其中而不是连接现有列表。您试图清理它只是复制了那些嵌套列表。您的第二次尝试无效,因为中的值
three不是列表,因此无法连接。我为那个值创建了一个新列表。您的最后一次尝试不应该
list.append()在生成器表达式中使用,因为您存储了该方法的返回值,它始终是None(它的更改v直接存储在其中,列表不需要再次返回)。
Demo of the first approach:
第一种方法的演示:
>>> one={'a': [1, 2], 'c': [5, 6], 'b': [3, 4]}
>>> two={'a': [2.4, 3.4], 'c': [5.6, 7.6], 'b': [3.5, 4.5]}
>>> three={'a': 1.2, 'c': 3.4, 'b': 2.3}
>>> {key: value + two[key] + [three[key]] for key, value in one.iteritems()}
{'a': [1, 2, 2.4, 3.4, 1.2], 'c': [5, 6, 5.6, 7.6, 3.4], 'b': [3, 4, 3.5, 4.5, 2.3]}
回答by HBS
See this help or not:
是否查看此帮助:
>>> dic={}
>>> k=[]
>>> for i in 'abc':
k=one[i]+two[i]
k.append(three[i])
dic[i]=k
>>> dic
{'c': [5, 6, 5.6, 7.6, 3.4], 'a': [1, 2, 2.4, 3.4, 1.2], 'b': [3, 4, 3.5, 4.5, 2.3]}
回答by jpp
Arbitrary dictionary number and keys
任意字典编号和键
The issues with your attempt are covered by @MartijnPieters' solution.
@MartijnPieters 的解决方案涵盖了您尝试的问题。
For a generalisedsolution, consider using itertools.chainto chain multiple dictionaries. You can also use a defaultdictfor the more general case where you do not find the same keys in each dictionary.
对于通用解决方案,请考虑使用itertools.chain链接多个字典。您还可以将 adefaultdict用于更一般的情况,即您在每个字典中找不到相同的键。
from collections import defaultdict
from itertools import chain
from operator import methodcaller
# dictionaries with non-equal keys, values all lists for simplicity
one = {'a': [1, 2], 'c': [5, 6], 'b': [3, 4], 'e': [6.2]}
two = {'a': [2.4, 3.4], 'c': [5.6, 7.6], 'b': [3.5, 4.5], 'f': [1.3]}
three = {'a': [1.2], 'c': [3.4], 'b': [2.3], 'e': [3.1]}
# initialise defaultdict of lists
dd = defaultdict(list)
# iterate dictionary items
dict_items = map(methodcaller('items'), (one, two, three))
for k, v in chain.from_iterable(dict_items):
dd[k].extend(v)
print(dd)
# defaultdict(list,
# {'a': [1, 2, 2.4, 3.4, 1.2],
# 'b': [3, 4, 3.5, 4.5, 2.3],
# 'c': [5, 6, 5.6, 7.6, 3.4],
# 'e': [6.2, 3.1],
# 'f': [1.3]})
Note defaultdictis a subclass of dictso there's generally no need to convert the result to a regular dict.
Notedefaultdict是 的子类,dict因此通常不需要将结果转换为常规dict.
回答by Deoclecio Freire
A robust solution. =)
一个强大的解决方案。=)
def FullMergeDict(D1, D2):
for key, value in D1.items():
if key in D2:
if type(value) is dict:
FullMergeDict(D1[key], D2[key])
else:
if type(value) in (int, float, str):
D1[key] = [value]
if type(D2[key]) is list:
D1[key].extend(D2[key])
else:
D1[key].append(D2[key])
for key, value in D2.items():
if key not in D1:
D1[key] = value
if __name__ == '__main__':
X = {
'a': 'aaa',
'c': [1,3,5,7],
'd': 100,
'e': {'k': 1, 'p': 'aa','t': [-1,-2]},
'f': {'j':1}
}
Y = {
'b': 'bbb',
'd': 200,
'e': {'k': 2, 'p': 'bb','o': [-4]},
'c': [2,4,6],
'g': {'v':2}
}
FullMergeDict(X, Y)
exit(0)
Result:
结果:
X = {
'a': 'aaa',
'b': 'bbb',
'c': [1, 3, 5, 7, 2, 4, 6],
'd': [100, 200],
'e': {'k': [1, 2], 'o': [-4], 'p': ['aa', 'bb'], 't': [-1, -2]},
'f': {'j': 1},
'g': {'v': 2}}
回答by Mykola Zotko
If you have different keys and different types of values in dictionaries you can use the following approach:
如果字典中有不同的键和不同类型的值,您可以使用以下方法:
from collections import defaultdict, Iterable
dct1 = {'a': [1, 2]}
dct2 = {'a': [3], 'b': [5, 6]}
dct3 = {'a': 4, 'c': 7}
result = defaultdict(list)
for dct in [dct1, dct2, dct3]:
for k, v in dct.items():
if isinstance(v, Iterable):
result[k].extend(v)
else:
result[k].append(v)
print(result)
# defaultdict(<class 'list'>, {'a': [1, 2, 3, 4], 'b': [5, 6], 'c': [7]})
回答by Shailesh Appukuttan
One line solution (also handles for keys present in only one dict):
一行解决方案(也处理仅存在于一个 dict 中的键):
{ key:one.get(key,[])+two.get(key,[]) for key in set(list(one.keys())+list(two.keys())) }
Example 1:
示例 1:
one = {'a': [1, 2], 'c': [5, 6], 'b': [3, 4]}
two = {'a': [2.4, 3.4], 'c': [5.6, 7.6], 'd': [3.5, 4.5]}
{ key:one.get(key,[])+two.get(key,[]) for key in set(list(one.keys())+list(two.keys())) }
Output:
输出:
{'a': [1, 2, 2.4, 3.4], 'b': [3, 4], 'c': [5, 6, 5.6, 7.6], 'd': [3.5, 4.5]}
{'a': [1, 2, 2.4, 3.4], 'b': [3, 4], 'c': [5, 6, 5.6, 7.6], 'd': [3.5, 4.5]}
Example 2:
示例 2:
x={1:['a','b','c']}
y={1:['d','e','f'],2:['g']}
{ key:x.get(key,[])+y.get(key,[]) for key in set(list(x.keys())+list(y.keys())) }
Output:
输出:
{1: ['a', 'b', 'c', 'd', 'e', 'f'], 2: ['g']}
{1: ['a', 'b', 'c', 'd', 'e', 'f'], 2: ['g']}

