2015-11-11 40 views
-1

我有一个嵌套的dictonary,我正在迭代,我想从旧dictonry中派生出一个新的dictonary,它根据旧值dictonary。为了说明:按照常见值在Python字典中分组项目

{'name': Fido, 'breed': Dalmatian, 'age': 3} 
{'name': Rex, 'breed': Dalmatian, 'age': 2} 
{'name': Max, 'breed': Dalmatian, 'age': 0} 
{'name': Rocky, 'breed': Pitbull, 'age': 6} 
{'name': Buster, 'breed': Pitbull, 'age': 7} 

能给我:

Dalmation: {'name': [Fido, Rex, Max], 'age': [3, 2, 0]} 
Pitbull : {'name': [Rocky, Buster], 'age': [6, 7]} 

我试图找到一个优雅和Python的解决方案,这都无济于事。

+1

那么你有什么尝试?你能给我们你的代码吗? –

+0

输入数据如何嵌套字典?另外为什么不告诉我们你的不合理/不合理的解决方案,以便我们可以提出改进建议,并且知道你至少已经努力解决你的问题。 –

回答

1
doglist = [ 
    {'name': 'Fido', 'breed': 'Dalmatian', 'age': 3}, 
    {'name': 'Rex', 'breed': 'Dalmatian', 'age': 2}, 
    {'name': 'Max', 'breed': 'Dalmatian', 'age': 0}, 
    {'name': 'Rocky', 'breed': 'Pitbull', 'age': 6}, 
    {'name': 'Buster', 'breed': 'Pitbull', 'age': 7}, 
] 
dogdict = {} 

for dog in doglist: 
    if dog['breed'] in dogdict: 
     dogdict[dog['breed']]['name'].append(dog['name']) 
     dogdict[dog['breed']]['age'].append(dog['age']) 
    else: 
     dogdict[dog['breed']] = {'name': [dog['name']], 'age': [dog['age']]} 
4

这里有两种可能性:

例子#1:http://ideone.com/RRzWaL

dogs = [ 
    {'name': 'Fido', 'breed': 'Dalmatian', 'age': 3}, 
    {'name': 'Rex', 'breed': 'Dalmatian', 'age': 2}, 
    {'name': 'Max', 'breed': 'Dalmatian', 'age': 0}, 
    {'name': 'Rocky', 'breed': 'Pitbull', 'age': 6}, 
    {'name': 'Buster', 'breed': 'Pitbull', 'age': 7}, 
] 

# get rid of duplicates 
breeds = set([ dog['breed'] for dog in dogs ]) 

breed_dict = {} 
for breed in breeds: 
    # get the names of all dogs corresponding to `breed` 
    names = [ dog['name'] for dog in dogs if dog['breed'] == breed ] 

    # get the ages of all dogs corresponding to `breed` 
    ages = [ dog['age'] for dog in dogs if dog['breed'] == breed ] 

    # add to the new dict 
    breed_dict[breed] = { 'age': ages, 'name': names } 

我也将添加使用collectionsdefaultdict的@ JohnGordon代码的简化:

例#2:http://ideone.com/B2xLGR

from collections import defaultdict 

doglist = [ 
    {'name': 'Fido', 'breed': 'Dalmatian', 'age': 3}, 
    {'name': 'Rex', 'breed': 'Dalmatian', 'age': 2}, 
    {'name': 'Max', 'breed': 'Dalmatian', 'age': 0}, 
    {'name': 'Rocky', 'breed': 'Pitbull', 'age': 6}, 
    {'name': 'Buster', 'breed': 'Pitbull', 'age': 7}, 
] 
dogdict = defaultdict(lambda: defaultdict(list)) 

for dog in doglist: 
    # `defaultdict` allows us to not have to check whether 
    # a key is already in the `dict`, it'll just set it to 
    # a default (`[]` in the inner dict in our case) 
    # if it's not there, and then append it. 
    dogdict[dog['breed']]['name'].append(dog['name']) 
    dogdict[dog['breed']]['age'].append(dog['age']) 

请注意,使用defaultdict的第二个示例将比第一个示例更快,该示例具有两个单独的列表解析(即两个单独的内部循环)。

0

使用itertools.groupby分隔词典,然后构建新的词典。

import itertools, collections, operator 
dees = [{'name': 'Fido', 'breed': 'Dalmatian', 'age': 3}, 
     {'name': 'Rex', 'breed': 'Dalmatian', 'age': 2}, 
     {'name': 'Max', 'breed': 'Dalmatian', 'age': 0}, 
     {'name': 'Rocky', 'breed': 'Pitbull', 'age': 6}, 
     {'name': 'Buster', 'breed': 'Pitbull', 'age': 7}] 

breed = operator.itemgetter('breed') 
filtr = ['name', 'age'] 
new_dees = [] 
for key, group in itertools.groupby(dees, breed): 
    d = collections.defaultdict(list) 
    for thing in group: 
     for k, v in thing.items(): 
      if k in filtr: 
       d[k].append(v) 
    new_dees.append({key:d}) 

作为替代你可以只提取你想要的,而不是使用if k in filtr值。我还没有决定我最喜欢哪个替代品,所以我也会发布这个。

# using previously defined functions and variables 
items_of_interest = operator.itemgetter(*filtr) 
for key, group in itertools.groupby(dees, breed): 
    d = collections.defaultdict(list) 
    for thing in group: 
     values = items_of_interest(thing) 
     for k, v in zip(filtr, values): 
      d[k].append(v) 
    new_dees.append({key:d})