比较dict列表并合并到一个python

2024-07-01 07:05:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个python程序,将类似的dict合并到一个dict中。我有两张单子。我有一个空的filter_cachedict。我有input_completed =false变量。我会用for循环得到dicts。在输入第一个dict之后,它被处理并合并成一个类似的dict,我将结果分配给filter_cachedict。通过for循环输入的列表中的下一个dict被处理并合并成一个。之后,我将input_completed改为true,因为data是空的。接下来,我要比较filter_cache中的前一个dict和当前的filter_cache,然后使用一些函数再次组合它并将它赋给fiter_cache。如何使之成为可能

代码如下:

from itertools import groupby

field_to_be_check = "state"
merger = ["city", "haps"]
merge_name = ["cities", "my_haps"]

data = [
[{'haps': 'hap0', 'state': 'tamil nadu','ads': 'ad1', 'city': 'tenkasi'},
{'haps': 'hap0', 'state': 'tamil nadu','ads': 'ad4', 'city': 'nagerkoil'},
{'haps': 'hap0', 'state': 'tamil nadu','ads': 'ad1', 'city': 'tuticorin'},
{'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'kolikodu'},
{'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'kottayam'},
{'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'idukki'},
{'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Akola'},
{'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Washim'},
{'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Jalna'},
{'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Latur'}],
[{'haps': 'hap1', 'state': 'tamil nadu','ads': 'ad1', 'city': 'madurai'},
{'haps': 'hap0', 'state': 'tamil nadu','ads': 'ad1', 'city': 'chennai'},
{'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'palakad'},
{'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'guruvayor'},
{'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Nanded'},
]
]


input_completed = False
filter_cache = {}
for datas in data:
    #Function to make the merger lists
    def process_group(group, merger_item):

        item_set = set()
        item_list = []
        for item in group:
            item_set.add(item[merger_item])

        for item in item_set:
            item_list.append({merger_item: item})

        return item_list

    #Group on haps, state and ads
    grp = groupby(datas,key=lambda x:(x[field_to_be_check]))
    result = []

    #Iterate through the group and build your result list
    for model, group in grp:
        cities_dict = {}

        cities_dict[field_to_be_check] = model

        group_list = list(group)

        #Make the list for merger fields
        for idx, name in enumerate(merger):
            cities_dict[merge_name[idx]] = process_group(group_list, name)

        result.append(cities_dict)
        filter_cache.update({'aggregate':result})
    print(filter_cache)


    final_result = filter_cache

我得到的输出:

{'aggregate': [{'state': 'tamil nadu', 'my_haps': [{'haps': 'hap0'}], 'cities': [{'city': 'tuticorin'}, {'city': 'tenkasi'}, {'city': 'nagerkoil'}]}, {'state': 'kerala', 'my_haps': [{'haps': 'hap1'}], 'cities': [{'city': 'idukki'}, {'city': 'kolikodu'}, {'city': 'kottayam'}]}, {'state': 'mumbai', 'my_haps': [{'haps': 'hap2'}], 'cities': [{'city': 'Akola'}, {'city': 'Jalna'}, {'city': 'Latur'}, {'city': 'Washim'}]}]}
{'aggregate': [{'state': 'tamil nadu', 'my_haps': [{'haps': 'hap1'}, {'haps': 'hap0'}], 'cities': [{'city': 'madurai'}, {'city': 'chennai'}]}, {'state': 'kerala', 'my_haps': [{'haps': 'hap1'}], 'cities': [{'city': 'palakad'}, {'city': 'guruvayor'}]}, {'state': 'mumbai', 'my_haps': [{'haps': 'hap2'}], 'cities': [{'city': 'Nanded'}]}]}

所需输出:

{'aggregate': [{'state': 'tamil nadu', 'my_haps': [{'haps': 'hap0'},{'haps': 'hap1'}], 'cities': [{'city': 'tuticorin'}, {'city': 'tenkasi'}, {'city': 'nagerkoil'},{'city': 'madurai'}, {'city': 'chennai'}]}, {'state': 'kerala', 'my_haps': [{'haps': 'hap1'}], 'cities': [{'city': 'idukki'}, {'city': 'kolikodu'}, {'city': 'kottayam'},{'city': 'palakad'}, {'city': 'guruvayor'}]}, {'state': 'mumbai', 'my_haps': [{'haps': 'hap2'}], 'cities': [{'city': 'Akola'}, {'city': 'Jalna'}, {'city': 'Latur'}, {'city': 'Washim'},{'city': 'Nanded'}]}]}

Tags: cityformygroupfilteritemdictads
2条回答

你的代码和被接受的答案在我看来过于复杂了(也许我不理解需求)。为什么不建立一个字典:field_to_be_check -> merger_name -> merger values,然后将它转换成所需的格式?你知道吗

词典的创建:

import itertools

data = [[{'haps': 'hap0', 'state': 'tamil nadu','ads': 'ad1', 'city': 'tenkasi'},
{'haps': 'hap0', 'state': 'tamil nadu','ads': 'ad4', 'city': 'nagerkoil'},
{'haps': 'hap0', 'state': 'tamil nadu','ads': 'ad1', 'city': 'tuticorin'},
{'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'kolikodu'},
{'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'kottayam'},
{'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'idukki'},
{'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Akola'},
{'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Washim'},
{'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Jalna'},
{'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Latur'}],
[{'haps': 'hap1', 'state': 'tamil nadu','ads': 'ad1', 'city': 'madurai'},
{'haps': 'hap0', 'state': 'tamil nadu','ads': 'ad1', 'city': 'chennai'},
{'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'palakad'},
{'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'guruvayor'},
{'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Nanded'},]]

field_to_be_check = "state"
name_by_merger = {"city": "cities", "haps": "my_haps"}

d = {}
for row in itertools.chain(*data):
    inner_d = d.setdefault(row[field_to_be_check], {})
    for m, n in name_by_merger.items():
        inner_d.setdefault(n, set()).add(row[m])

d的内容:

{'tamil nadu': {'cities': {'chennai', 'nagerkoil', 'tuticorin', 'madurai', 'tenkasi'}, 'my_haps': {'hap0', 'hap1'}}, 'kerala': {'cities': {'kolikodu', 'palakad', 'idukki', 'guruvayor', 'kottayam'}, 'my_haps': {'hap1'}}, 'mumbai': {'cities': {'Nanded', 'Latur', 'Jalna', 'Akola', 'Washim'}, 'my_haps': {'hap2'}}}

函数itertools.chain包含两个列表。如果需要,setdefault方法在字典中创建一个新条目。你知道吗

转换成所需的格式只是一个难看的听写理解:

{'aggregate': [{field_to_be_check: k, **{n: [{m: x} for x in v[n]] for m, n in name_by_merger.items()}} for k, v in d.items()]}

输出:

{'aggregate': [{'state': 'tamil nadu', 'cities': [{'city': 'chennai'}, {'city': 'nagerkoil'}, {'city': 'tuticorin'}, {'city': 'madurai'}, {'city': 'tenkasi'}], 'my_haps': [{'haps': 'hap0'}, {'haps': 'hap1'}]}, {'state': 'kerala', 'cities': [{'city': 'kolikodu'}, {'city': 'palakad'}, {'city': 'idukki'}, {'city': 'guruvayor'}, {'city': 'kottayam'}], 'my_haps': [{'haps': 'hap1'}]}, {'state': 'mumbai', 'cities': [{'city': 'Nanded'}, {'city': 'Latur'}, {'city': 'Jalna'}, {'city': 'Akola'}, {'city': 'Washim'}], 'my_haps': [{'haps': 'hap2'}]}]}

当然,您可以一次生成所需的输出,但是由于格式很麻烦,我认为首先创建一个nive字典,然后遵循此格式更为简洁。你知道吗

功能:

def group_dicts_from_list(lst, group_by, merge_rules, result):
    if not lst or not isinstance(lst, list) or not group_by or not merge_rules or \
            not isinstance(merge_rules, dict) or not isinstance(result, dict):
        return
    if "aggregate" not in result:
        result["aggregate"] = []
    for item in lst:
        if isinstance(item, dict):
            if group_by in item:
                for res in result["aggregate"]:
                    if res[group_by] == item[group_by]:
                        tmp = res
                        break
                else:
                    tmp = {group_by: item[group_by]}
                    result["aggregate"].append(tmp)
                for src, dst in merge_rules.items():
                    if src in item:
                        if dst not in tmp:
                            tmp[dst] = []
                        src_tmp = {src: item[src]}
                        if src_tmp not in tmp[dst]:
                            tmp[dst].append(src_tmp)
        elif isinstance(item, list):
            group_dicts_from_list(item, group_by, merge_rules, result) # !!! recursion !!! 

用法:

field_to_be_check = "state"
my_merge_rules = {
    "city": "cities",
    "haps": "my_haps",
}
data = [
    [{'haps': 'hap0', 'state': 'tamil nadu', 'ads': 'ad1', 'city': 'tenkasi'},
     {'haps': 'hap0', 'state': 'tamil nadu', 'ads': 'ad4', 'city': 'nagerkoil'},
     {'haps': 'hap0', 'state': 'tamil nadu', 'ads': 'ad1', 'city': 'tuticorin'},
     {'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'kolikodu'},
     {'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'kottayam'},
     {'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'idukki'},
     {'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Akola'},
     {'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Washim'},
     {'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Jalna'},
     {'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Latur'}],
    [{'haps': 'hap1', 'state': 'tamil nadu', 'ads': 'ad1', 'city': 'madurai'},
     {'haps': 'hap0', 'state': 'tamil nadu', 'ads': 'ad1', 'city': 'chennai'},
     {'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'palakad'},
     {'haps': 'hap1', 'state': 'kerala', 'ads': 'ad2', 'city': 'guruvayor'},
     {'haps': 'hap2', 'state': 'mumbai', 'ads': 'ad3', 'city': 'Nanded'},
     ]
]

result = {}
group_dicts_from_list(data, field_to_be_check, my_merge_rules, result)

print(result)

输出:

{'aggregate': [{'state': 'tamil nadu', 'cities': [{'city': 'tenkasi'}, {'city': 'nagerkoil'}, {'city': 'tuticorin'}, {'city': 'madurai'}, {'city': 'chennai'}], 'my_haps': [{'haps': 'hap0'}, {'haps': 'hap1'}]}, {'state': 'kerala', 'cities': [{'city': 'kolikodu'}, {'city': 'kottayam'}, {'city': 'idukki'}, {'city': 'palakad'}, {'city': 'guruvayor'}], 'my_haps': [{'haps': 'hap1'}]}, {'state': 'mumbai', 'cities': [{'city': 'Akola'}, {'city': 'Washim'}, {'city': 'Jalna'}, {'city': 'Latur'}, {'city': 'Nanded'}], 'my_haps': [{'haps': 'hap2'}]}]}

评论:

我已经换了

merger = ["city", "haps"]
merge_name = ["cities", "my_haps"]

my_merge_rules = {
    "city": "cities",
    "haps": "my_haps",
}

因为我发现它更可靠(它可以防止列表长度不同的情况)。你知道吗

相关问题 更多 >

    热门问题