使用UID结合了3个DICS的列表



我有三个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}]})

使用我想创建1个看起来像以下内容的用户上的共享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}}])

当我使用嵌套循环的2个列表时,我已经解决了它,但是代码超级凌乱,感觉不太好,现在我正在使用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)

在这里为此一个简单的功能:

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}]}]

您可以使用 itertools.groupby(doc(进行分组元素:

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}}}

也许这个词典会更好地操纵。

反对方向的解决方案

# Data structure to manage shared object information
class shared(object):
  def __init__(self, i):
    self.i = i
    self.users = dict()
  # Add information of the particulate user
  def update_user(self, user_id, key, value):
    if user_id in self.users:
      self.users[user_id][key] = value
    else:
      self.users[user_id]= {key:value,
                            "id":user_id, 
                            "combined_id": "{0}{1}".format(user_id,self.i)}      
  # Return the information is required format
  def get(self):
    return  {
        'shared_id': self.i,
        'users' : [ user for user in self.users.values()]
    }

数据

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}]})

解析数据

info = {}
for l in list_1+list_2+list_3:
  # Is there already information for this shared_id ?
  if l["shared_id"] not in info:
    info[l["shared_id"]] = shared(l["shared_id"])
  # Parse all the users  
  for user_info in l['users']:
    user_id = user_info["id"]
    # Parse the user information
    for key,value in user_info.items():
      if key != "id":
        # Update the user information
        info[l["shared_id"]].update_user(user_id, key, value)

result = [x.get() for x in info.values()]
print (result)

输出

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

您可以使用itertools.groupby()将ID分组在一起,然后根据需要合并字典:

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}]}]
global_list = []
def add_item(item):
    item_found = False
    for e_item in global_list:
        if e_item['shared_id'] == item['shared_id']:
            item_found = True
            e_users = e_item['users']
            users = item['users']
            for user in users:
                user_found = False
                for e_user in e_users:
                    if e_user['id'] == user['id']:
                        user_found = True
                        e_user.update(user)
                if user_found is False:
                    e_users.append(user)
    if item_found is False:
        global_list.append(item)    

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}]})
for item in list_1+list_2+list_3:
    add_item(item)
print(global_list)

相关内容

  • 没有找到相关文章

最新更新