按嵌套值过滤/分组字典

时间:2017-11-03 22:07:24

标签: python dictionary

以下是我所拥有的一些数据的简化示例:

{"id": "1234565", "fields": {"name": "john", "email":"john@example.com", "country": "uk"}}

全嵌套字典是一个更大的地址数据列表。目标是从列表中创建成对的人与随机合作伙伴,其中应优先选择来自同一国家/地区的合作伙伴。所以我的第一个真正的问题是找到一种按国家价值对它们进行分组的好方法。

我确信有更聪明的方法可以做到这一点,而不是遍历dict并将所有记录写入一些新的列表/字典?

2 个答案:

答案 0 :(得分:4)

我认为这接近你所需要的:

result = {key:[i for i in value] for key, value in itertools.groupby(people, lambda item: item["fields"]["country"])}

这样做是使用itertools.groupby按指定国家/地区对people列表中的所有人进行分组。生成的字典将国家/地区作为键,将解压缩的分组(匹配人员)作为值。输入应该是一个字典列表,如示例中的字典:

people = [{"id": "1234565", "fields": {"name": "john", "email":"john@example.com", "country": "uk"}}, 
          {"id": "654321", "fields": {"name": "sam", "email":"sam@example.com", "country": "uk"}}]

示例输出:

>>> print(result)
>>> {'uk': [{'fields': {'name': 'john', 'email': 'john@example.com', 'country': 'uk'}, 'id': '1234565'}, {'fields': {'name': 'sam', 'email': 'sam@example.com', 'country': 'uk'}, 'id': '654321'}]}

为了获得更清晰的结果,可以调整循环结构,以便结果字典中只包含每个人的ID:

result = {key:[i["id"] for i in value] for key, value in itertools.groupby(people, lambda item: item["fields"]["country"])}
>>> print(result)
>>> {'uk': ['1234565', '654321']}

编辑:抱歉,我忘记了排序。在通过groupby之前,只需按国家/地区对人员列表进行排序。它现在应该正常工作:

sort = sorted(people, key=lambda item: item["fields"]["country"])

答案 1 :(得分:0)

这是另一个使用defaultdict:

import collections

def make_groups(nested_dicts, nested_key):
    default = collections.defaultdict(list)
    for nested_dict in nested_dicts:
        for value in nested_dict.values():
            try:
                default[value[nested_key]].append(nested_dict)
            except TypeError:
                pass
    return default

测试结果:

import random

COUNTRY = {'af', 'br', 'fr', 'mx', 'uk'}

people = [{'id': i, 'fields': {
                               'name': 'name'+str(i),
                               'email': str(i)+'@email',
                               'country': random.sample(COUNTRY, 1)[0]}} 
          for i in range(10)]

country_groups = make_groups(people, 'country')

for country, persons in country_groups.items():
    print(country, persons)

随机输出:

fr [{'id': 0, 'fields': {'name': 'name0', 'email': '0@email', 'country': 'fr'}}, {'id': 1, 'fields': {'name': 'name1', 'email': '1@email', 'country': 'fr'}}, {'id': 4, 'fields': {'name': 'name4', 'email': '4@email', 'country': 'fr'}}]
br [{'id': 2, 'fields': {'name': 'name2', 'email': '2@email', 'country': 'br'}}, {'id': 8, 'fields': {'name': 'name8', 'email': '8@email', 'country': 'br'}}]
uk [{'id': 3, 'fields': {'name': 'name3', 'email': '3@email', 'country': 'uk'}}, {'id': 7, 'fields': {'name': 'name7', 'email': '7@email', 'country': 'uk'}}]
af [{'id': 5, 'fields': {'name': 'name5', 'email': '5@email', 'country': 'af'}}, {'id': 9, 'fields': {'name': 'name9', 'email': '9@email', 'country': 'af'}}]
mx [{'id': 6, 'fields': {'name': 'name6', 'email': '6@email', 'country': 'mx'}}]