使用uid合并3个dict列表

2024-05-19 23:03:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我有三个dict列表,一些示例数据可以如下所示:

list_1.append({"shared_id": "111", "users": [{"id": "444", "opens": 2}, {"id": "555", "opens": 2}]})
list_1.append({"shared_id": "222", "users": [{"id": "444", "opens": 2}, {"id": "555", "opens": 3}]})

list_2.append({"shared_id": "111", "users": [{"id": "444", "clicks": 1}, {"id": "555", "clicks": 2}]})
list_2.append({"shared_id": "222", "users": [{"id": "444", "clicks": 3}, {"id": "555", "clicks": 3}]})

list_3.append({"shared_id": "111", "users": [{"id": "444", "bounces": 2}, {"id": "555", "bounces": 1}]})
list_3.append({"shared_id": "222", "users": [{"id": "444", "bounces": 3}, {"id": "555", "bounces": 2}]})

使用共享id和用户上的id,我要创建一个组合列表,如下所示:

combined_list.append([{"shared_id": "111", "users": [{"id": "444", "opens": 2, "clicks": 1, "bounces": 2, "combined_id": 444111}, {"id": "555", "opens": 3, "clicks": 2, "bounces": 1, "combined_id": 555111}}])

combined_list.append([{"shared_id": "222", "users": [{"id": "444", "opens": 2, "clicks": 3, "bounces": 1, "combined_id": 444222}, {"id": "555", "opens": 3, "clicks": 3, "bounces": 2, "combined_id": 555222}}])

当我有两个使用嵌套for循环的列表时,我已经解决了这个问题,但是代码非常混乱,感觉不是很pythonized,现在有没有更好的方法来使用3个列表?你知道吗

for o in list_1:
        for c in list_2:
            if o['shared_id'] == c['shared_id']:
                csd = {
                    'users': [],
                    'shared_id': o['shared_id']
                }
                for op in o['users']:
                    for cp in c['users']:
                        if op['id'] == cp['id']:
                            cpd = {
                                'opens': op['opens'],
                                'clicks': cp['clicks'],
                                'combined_id': '{}{}'.format(
                                    op['id'],
                                    csd['shared_id']
                                    )
                            }

                            csd['users'].append(cpd)

                combined.append(csd)

Tags: inid列表forcpuserslistshared
3条回答

这里有一个简单的函数:

from pprint import pprint

def combine_lists(*lists):
    result = {}
    # For each list
    for lst in lists:
        # For each dict in the list
        for d1 in lst:
            # Get or make common dict for shared_id
            shared_id = d1["shared_id"]
            shared_dict = result.setdefault(shared_id, {})
            # For each user dict in the dict
            for d2 in d1["users"]:
                # Get or make user dict
                user_id = d2["id"]
                if user_id not in shared_dict:
                    shared_dict[user_id] = {"combined_id": "{}{}".format(user_id, shared_id)}
                # Update information in user dictionary
                shared_dict[user_id].update(d2)
    # Make output as a list
    return [{"shared_id": k, "users": list(v.values())} for k, v in result.items()]

# Test
list_1 = []
list_1.append({"shared_id": "111", "users": [{"id": "444", "opens": 2}, {"id": "555", "opens": 2}]})
list_1.append({"shared_id": "222", "users": [{"id": "444", "opens": 2}, {"id": "555", "opens": 3}]})
list_2 = []
list_2.append({"shared_id": "111", "users": [{"id": "444", "clicks": 1}, {"id": "555", "clicks": 2}]})
list_2.append({"shared_id": "222", "users": [{"id": "444", "clicks": 3}, {"id": "555", "clicks": 3}]})
list_3 = []
list_3.append({"shared_id": "111", "users": [{"id": "444", "bounces": 2}, {"id": "555", "bounces": 1}]})
list_3.append({"shared_id": "222", "users": [{"id": "444", "bounces": 3}, {"id": "555", "bounces": 2}]})

pprint(combine_lists(list_1, list_2, list_3))
# [{'shared_id': '111',
#   'users': [{'bounces': 2,
#              'clicks': 1,
#              'combined_id': '444111',
#              'id': '444',
#              'opens': 2},
#             {'bounces': 1,
#              'clicks': 2,
#              'combined_id': '555111',
#              'id': '555',
#              'opens': 2}]},
#  {'shared_id': '222',
#   'users': [{'bounces': 3,
#              'clicks': 3,
#              'combined_id': '444222',
#              'id': '444',
#              'opens': 2},
#             {'bounces': 2,
#              'clicks': 3,
#              'combined_id': '555222',
#              'id': '555',
#              'opens': 3}]}]

可以使用^{}将ID分组,然后根据需要使用merge词典:

from collections import ChainMap
from itertools import chain, groupby
from operator import itemgetter

combined_list = []
for k, g in groupby(sorted(chain(list_1, list_2, list_3), key=itemgetter('shared_id')), key=itemgetter('shared_id')):
    users = []
    for k2, g2 in groupby(sorted(chain(*map(itemgetter('users'), g)), key=itemgetter('id')), key=itemgetter('id')):
        users.append({'id': k2, 'combined_id': k2 + k, **ChainMap(*g2)})

    combined_list.append({'shared_id': k, 'users': users})
print(combined_list)

输出:

[{'shared_id': '111', 'users': [{'id': '444', 'combined_id': '444111', 'bounces': 2, 'clicks': 1, 'opens': 2}, {'id': '555', 'combined_id': '555111', 'bounces': 1, 'clicks': 2, 'opens': 2}]}, {'shared_id': '222', 'users': [{'id': '444', 'combined_id': '444222', 'bounces': 3, 'clicks': 3, 'opens': 2}, {'id': '555', 'combined_id': '555222', 'bounces': 2, 'clicks': 3, 'opens': 3}]}]

可以使用itertools.groupbydoc)对元素进行分组:

list_1, list_2, list_3 = [], [], []

list_1.append({"shared_id": "111", "users": [{"id": "444", "opens": 2}, {"id": "555", "opens": 2}]})
list_1.append({"shared_id": "222", "users": [{"id": "444", "opens": 2}, {"id": "555", "opens": 3}]})

list_2.append({"shared_id": "111", "users": [{"id": "444", "clicks": 1}, {"id": "555", "clicks": 2}]})
list_2.append({"shared_id": "222", "users": [{"id": "444", "clicks": 3}, {"id": "555", "clicks": 3}]})

list_3.append({"shared_id": "111", "users": [{"id": "444", "bounces": 2}, {"id": "555", "bounces": 1}]})
list_3.append({"shared_id": "222", "users": [{"id": "444", "bounces": 3}, {"id": "555", "bounces": 2}]})

from itertools import groupby

shared_ids = {}
for v, g in groupby(sorted(list_1 + list_2 + list_3, key=lambda k: k['shared_id']), lambda k: k['shared_id']):
    for shared_id in g:
        for user in shared_id['users']:
            shared_ids.setdefault(v, {}).setdefault(user['id'], {}).update(**user)
            shared_ids[v][user['id']]['combined_id'] = '{}{}'.format(user['id'], v)


out = [{'shared_id': k, 'users': [shared_ids[k][kk] for kk in shared_ids[k]]} for k in shared_ids]

from pprint import pprint
pprint(out)

印刷品:

[{'shared_id': '111',
  'users': [{'bounces': 2, 'clicks': 1, 'combined_id': '444111', 'id': '444', 'opens': 2},
            {'bounces': 1, 'clicks': 2, 'combined_id': '555111', 'id': '555', 'opens': 2}]},
 {'shared_id': '222',
  'users': [{'bounces': 3, 'clicks': 3, 'combined_id': '444222', 'id': '444', 'opens': 2},
            {'bounces': 2, 'clicks': 3, 'combined_id': '555222', 'id': '555', 'opens': 3}]}]

注意:如果您打印shared_ids变量,您将得到:

{'111': {'444': {'bounces': 2, 'clicks': 1, 'combined_id': '444111', 'id': '444', 'opens': 2},
         '555': {'bounces': 1, 'clicks': 2, 'combined_id': '555111', 'id': '555', 'opens': 2}},
 '222': {'444': {'bounces': 3, 'clicks': 3, 'combined_id': '444222', 'id': '444', 'opens': 2},
         '555': {'bounces': 2, 'clicks': 3, 'combined_id': '555222', 'id': '555', 'opens': 3}}}

也许这本词典更适合进一步操作。你知道吗

相关问题 更多 >