繁体   English   中英

根据某些键/值对从合并列表中合并dicts

[英]Merge dicts from a list of dicts based on some key/value pair

我有一个下面显示的dicts列表,我想将一些dicts合并为一个基于某个键/值对。

 [
    {'key': 16, 'value': 3, 'user': 3, 'id': 7}, 
    {'key': 17, 'value': 4, 'user': 3, 'id': 7}, 
    {'key': 17, 'value': 5, 'user': 578, 'id': 7}, 
    {'key': 52, 'value': 1, 'user': 3, 'id': 48}, 
    {'key': 46, 'value': 2, 'user': 578, 'id': 48}
]

现在您可以看到dict 1 & 2具有相同的用户id键值。 所以有可能合并这两个词

 [
    {'key': [16,17], 'value': [3,4], 'user': 3, 'id': 7}, 
    {'key': [17], 'value': [5], 'user': 578, 'id': 7}, 
    {'key': [52], 'value': [1], 'user': 3, 'id': 48}, 
    {'key': [46], 'value': [2], 'user': 578, 'id': 48}
]

意味着user & id值必须是唯一的。什么是合并的有效方式(如果可能的话)

以下函数将字典列表转换为新格式:

def convert(d):
    res = {}
    for x in d:
        key = (x['user'], x['id'])
        if key in res:
            res[key]['key'].append(x['key'])
            res[key]['value'].append(x['value'])
        else:
            x['key'] = [x['key']]
            x['value'] = [x['value']]
            res[key] = x

    return res.values()

它将改变原始词典,结果中词典的顺序将是随机的。 当应用于输入时,它将产生以下结果:

[
    {'id': 7, 'value': [5], 'key': [17], 'user': 578}, 
    {'id': 7, 'value': [3, 4], 'key': [16, 17], 'user': 3}, 
    {'id': 48, 'value': [1], 'key': [52], 'user': 3}, 
    {'id': 48, 'value': [2], 'key': [46], 'user': 578}
]

dicts成为您原始的词典列表。 这个想法将用户和id的唯一组合映射到defaultdict(list)对象。 最终结果将是该字典中的值列表。

from collections import defaultdict
tmp = defaultdict(dict)

for info in dicts:
    tmp[(info['user'], info['id'])].setdefault('key', []).append(info['key'])
    tmp[(info['user'], info['id'])].setdefault('value', []).append(info['value'])

for (user, id_), d in tmp.items(): # python2: use iteritems
    d.update(dict(user=user, id=id_))

result = list(tmp.values()) # python2: tmp.values() already gives a list
del tmp

您可以使用以下聚合函数:

def aggregate(lst):
    new = {}
    for d in lst:
        new.setdefault((d['user'], d['id']), []).append(d)
    for k, d in new.items():
        if len(d) > 1:
            keys, values = zip(*[(sub['key'], sub['value']) for sub in d])
            user, id_ = k
            yield {'key': keys, 'value': values, 'user': user, 'id': id_}
        else:
            yield d[0]

print list(aggregate(lst))
[{'id': 7, 'value': 5, 'key': 17, 'user': 578},
 {'id': 7, 'value': (3, 4), 'key': (16, 17), 'user': 3},
 {'id': 48, 'value': 1, 'key': 52, 'user': 3},
 {'id': 48, 'value': 2, 'key': 46, 'user': 578}]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM