Python词典:基于公共密钥值对密钥,值对进行分组

时间:2015-03-22 04:48:34

标签: python dictionary

我有一个包含这样字典的列表:

list1 = [{'name': 'bob', 'email': 'bob@bob.com', 'address': '123 house lane', 
'student_id': 12345}, {'name': 'steve', 'email': 'steve@steve.com',
'address': '456 house lane', 'student_id': 34567}, {'name': 'bob',
'email': 'bob2@bob2.com', 'address': '789 house lane', 'student_id': 45678}]

在python中是否有办法根据' name'对新词典中的选定键,值对进行分组?值?例如,这样的结果是最终结果:

new_list = [
    {'name': 'bob', 
         {'emails': ['bob@bob.com', 
                    'bob2@bob2.com']}, 
         {'address': ['123 house lane', 
                    '789 house lane']},
    {'name': 'steve',
        {'email': ... },
        {'address': ... }}
      # let's assume the list1 has various entries at some point 
      # which may or may not have duplicate 'name' values
      # and new_list will hold the groupings
]

2 个答案:

答案 0 :(得分:1)

听起来这就是你想要做的事情:

list1 = [{'name': 'bob', 'email': 'bob@bob.com', 
          'address': '123 house lane', 'student_id': 12345},
         {'name': 'steve', 'email': 'steve@steve.com',
          'address': '456 house lane', 'student_id': 34567},
         {'name': 'bob', 'email': 'bob2@bob2.com',
          'address': '789 house lane', 'student_id': 45678}]

import operator
list1.sort(key=operator.itemgetter('name'))

new_list = []
for studentname, dicts in itertools.groupby(list1, operator.itemgetter('name')):
    d = {'name': studentname}
    for dct in dicts:
        for key,value in dct.items():
            if key == 'name':
                continue
            d.setdefault(key, []).append(value)
    new_list.append(d)

样本:

[{'address': ['123 house lane', '789 house lane'],
  'email': ['bob@bob.com', 'bob2@bob2.com'],
  'name': 'bob',
  'student_id': [12345, 45678]},
 {'address': ['456 house lane'],
  'email': ['steve@steve.com'],
  'name': 'steve',
  'student_id': [34567]}]

如果你打算广泛使用它,你可能应该硬编码一些更好的名字(例如addresses而不是address)并制作一个为你填充它们的映射。

keys_mapping = {'address': 'addresses',
                'email': 'emails',
                'student_id': 'student_ids'}

for studentname, dicts in itertools.groupby(list1, operator.itemgetter('name')):
    d = {'name': studentname}
    for dct in dicts:
        for key,value in dct_items():
            new_key = keys_mapping.get(key,key)
            # get the updated value if it's defined, else give `key`
            d.setdefault(new_key, []).append(value)
    new_list.append(d)

答案 1 :(得分:1)

下面的代码为您提供嵌套字典。嵌套字典可以让您更快地找到密钥,而在列表中则必须创建循环。

list1 = [{'name': 'bob', 'email': 'bob@bob.com', 'address': '123 house lane', 
'student_id': 12345}, {'name': 'steve', 'email': 'steve@steve.com',
'address': '456 house lane', 'student_id': 34567}, {'name': 'bob',
'email': 'bob2@bob2.com', 'address': '789 house lane', 'student_id': 45678}]

dict1 = {}
for content in list1:
    if content['name'] in [name for name in dict1]:
        dict1[content['name']] = {'emails': dict1[content['name']]['emails'] + [content['address']], 'addresses': dict1[content['name']]['addresses'] + [content['email']]}
    else:
        dict1[content['name']] = {'emails': [content['email']], 'addresses': [content['address']]}
print dict1

代码输出

{'steve': {'emails': ['steve@steve.com'], 'addresses': ['456 house lane']}, 'bob': {'emails': ['bob@bob.com', '789 house lane'], 'addresses': ['123 house lane', 'bob2@bob2.com']}}