List中的字典::合并相同键的值

时间:2012-10-08 13:03:11

标签: python data-structures data-dictionary

我在Python List中有多个词典,如下所示

[{"color": "#CC3", "values": {"y": 83, "x": 9}, "key": 105},
 {"color": "#CC3", "values": {"y": 123, "x": 10}, "key": 105},
 {"color": "#FF9", "values": {"y": 96, "x": 11}, "key": 106},
 {"color": "#33F", "values": {"y": 80, "x": 12}, "key": 104},
 {"color": "#CC3", "values": {"y": 117, "x": 13}, "key": 105},
 {"color": "#CC3", "values": {"y": 115, "x": 14}, "key": 105},
 {"color": "#CC3", "values": {"y": 102, "x": 15}, "key": 105},
 {"color": "#FF9", "values": {"y": 111, "x": 16}, "key": 106},
 {"color": "#FF9", "values": {"y": 33, "x": 17}, "key": 106}]

在上面包含词典的列表中,有一些名为“key”的键,其值相同,例如: 105,106等,在那些字典中,“值”的值变化,例如, 105 "values": {"y": 83, "x": 9}"values": {"y": 117, "x": 13}

我想在一个词典中添加并带来相同“key = xxx”词典的值

例如,对于密钥= 105的字典,我想汇总“值”:[{"y": 83, "x": 9},{"y": 117, "x": 13}]在这样的列表中说

最终合并输出应保留上面引用的原始结构

[{"color"="...","values"=[{...},{...}],"key"="..."},....]

实现这一目标的最佳方法是什么?

4 个答案:

答案 0 :(得分:4)

您可以使用collections.defaultdict

如果您向其提供list,则会在访问新密钥时自动创建空列表。

from collections import defaultdict

a = [{"color": "#CC3", "values": {"y": 83, "x": 9}, "key": 105}, {"color": "#CC3", "values": {"y": 123, "x": 10}, "key": 105}, {"color": "#FF9", "values": {"y": 96, "x": 11}, "key": 106}, {"color": "#33F", "values": {"y": 80, "x": 12}, "key": 104}, {"color": "#CC3", "values": {"y": 117, "x": 13}, "key": 105}, {"color": "#CC3", "values": {"y": 115, "x": 14}, "key": 105}, {"color": "#CC3", "values": {"y": 102, "x": 15}, "key": 105}, {"color": "#FF9", "values": {"y": 111, "x": 16}, "key": 106}, {"color": "#FF9", "values": {"y": 33, "x": 17}, "key": 106}]

result = defaultdict(list)

for d in a:
    result[d['key']].append(d['values'])

dict(result)现在是:

{104: [{'y': 80, 'x': 12}],
 105: [{'y': 83, 'x': 9}, {'y': 123, 'x': 10}, {'y': 117, 'x': 13}, {'y': 115, 'x': 14}, {'y': 102, 'x': 15}],
 106: [{'y': 96, 'x': 11}, {'y': 111, 'x': 16}, {'y': 33, 'x': 17}]}

答案 1 :(得分:1)

data=[{"color": "#CC3", "values": {"y": 83, "x": 9}, "key": 105}, {"color": "#CC3", "values": {"y": 123, "x": 10}, "key": 105}, {"color": "#FF9", "values": {"y": 96, "x": 11}, "key": 106}, {"color": "#33F", "values": {"y": 80, "x": 12}, "key": 104}, {"color": "#CC3", "values": {"y": 117, "x": 13}, "key": 105}, {"color": "#CC3", "values": {"y": 115, "x": 14}, "key": 105}, {"color": "#CC3", "values": {"y": 102, "x": 15}, "key": 105}, {"color": "#FF9", "values": {"y": 111, "x": 16}, "key": 106}, {"color": "#FF9", "values": {"y": 33, "x": 17}, "key": 106}]

databykey={}   #make a new dictionary
for l in data:   # for each item in the list
 if l['key'] in databykey: databykey[l['key']]['values'].append(l['values'])
 else: databykey[l['key']]={'color':l['color'], 'values':[l['values']]}
 # if the item's key is already in the dictionary, add its values to the list
 # else, add the key to the dictionary with the color and the first value

databykey现在

{104: {'color': '#33F', 'values': [{'y': 80, 'x': 12}]},
 105: {'color': '#CC3','values': [{'y': 83, 'x': 9}, {'y': 123, 'x': 10}, {'y': 117, 'x': 13}, {'y': 115, 'x': 14}, {'y': 102, 'x': 15}]},
 106: {'color': '#FF9', 'values': [{'y': 96,'x': 11}, {'y': 111, 'x': 16}, {'y': 33, 'x': 17}]}}

答案 2 :(得分:0)

尝试这样的事情:

dicts = [{...}, {...}]

def get_values(key):
    return [d["values"] for d in dicts if d["key"] == key]

values_for_105 = get_values(105)

对于您的示例values_for_105

[{'y': 83, 'x': 9}, 
 {'y': 123, 'x': 10}, 
 {'y': 117, 'x': 13}, 
 {'y': 115, 'x': 14}, 
 {'y': 102, 'x': 15}]

答案 3 :(得分:0)

如果您只想根据密钥对元素进行分组,那么使用itertools.groupby函数并直接执行此操作,而不会产生创建defaultdict实例的繁杂开销:

import itertools

def key_func(elem):
    return elem["key"]

[{k:list(elem)} for k, elem in itertools.groupby(list_of_dicts, key_func)]

这会产生:

[{100: [{'key': 100, 'x': 10, 'y': 20}, {'key': 100, 'x': 5, 'y': 3.4}]},
 {200: [{'key': 200, 'x': 44, 'y': 3.14}, {'key': 200, 'x': -44, 'y': 3.14}]}]

(来自我下面的测试示例)。

这是一种更强大的方法来解决这个问题,因为(a)它将原始键留在了dicts中(如果你愿意,你可以选择忽略它,但是你并不局限于删除它们......所以这个(b)你可以做分组操作/聚合(例如下面的例子)。

假设您的初始词典列表名为list_of_dicts,并且您希望将新的词典列表作为输出,只需将xy条目汇总在一起即可汇总。< / p>

[
 reduce(
        lambda a,b: {"key":a["key"], "x":a["x"]+b["x"], "y":a["y"]+b["y"]},
        list(elem)
       ) 
 for k, elem in itertools.groupby(list_of_dicts, key_func)
]

如果我使用以下测试输入运行:

list_of_dicts = [
                 {"key":100, "x":10, "y":20}, 
                 {"key":100, "x":5, "y":3.4}, 
                 {"key":200, "x":44, "y":3.14}, 
                 {"key":200, "x":-44, "y":3.14}
                ]

然后我得到以下结果:

print [reduce(lambda a,b: {"key":a["key"], "x":a["x"]+b["x"], "y":a["y"]+b["y"]}, list(elem)) for k, elem in itertools.groupby(list_of_dicts, key_func)]

[{'key': 100, 'x': 15, 'y': 23.4}, {'key': 200, 'x': 0, 'y': 6.28}]