按共同值

时间:2015-11-11 23:17:52

标签: python dictionary grouping

我有一个嵌套的dictonary,我正在迭代,我想制作一个新的dictonary来源于旧的dictonry根据旧dictonary中存在的值将某些值组合在一起。举例说明:

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

我试图找到一个优雅和pythonic解决方案,但无济于事。

3 个答案:

答案 0 :(得分: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 }

我还会使用collections的{​​{1}}添加@ JohnGordon代码的简化:

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

defaultdict

请注意,使用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']) 的第二个示例将比第一个示例更快,第一个示例有两个单独的列表推导(即两个独立的内部循环)。

答案 1 :(得分: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']]}

答案 2 :(得分: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})