2015-11-11 62 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})