Python 从包含字典的嵌套列表创建新列表

Python Creating a new list from a nested list containing Dictionaries

给出的是包含字典的输入列表。

Input=[
       {"rbd":"x","cat":"xxx","origin":"us"},
       {"rbd":"y","cat":"xxx","origin":"us"},
       {"rbd":"z","cat":"xxx","origin":"us"},
       {"rbd":"q","cat":"xxx","origin":"us"},
       {"rbd":"1","cat":"xxy","origin":"us"},
       {"rbd":"2","cat":"xxy","origin":"us"}
                                              ]

我正在尝试将其作为输出。 在这里,如果键“cat”和键“origin”对于输入列表中的字典是相同的,那么它会将它们添加到一个“rbd”中。否则它会创建一个新的。下面是输出。

Output=[{"rbd":["x","y","z","q"],"cat":"xxx","origin":"us"},
        {"rbd":["l","2"],"cat":"xxy","origin":"us"}]

我尝试了以下不完整的实现。首先将列表转换成字典。它会引发错误。

def Convert(lst): 
    Input_Dict = {lst[i]: lst[i + 1] for i in range(0, len(lst), 2)} 
    return Input_Dict

您应该遍历输入,并为每个元素检查输出中是否存在 cat 和 origin。如果已经存在,则将 Input 的 rbd 放在 Output 中。如果不存在,则在 Output 中创建一个新地图。

请注意,这不是最有效的答案。

尝试 itertools.groupby:

from itertools import groupby

Input = [{"rbd": "x", "cat": "xxx", "origin": "us"},
         {"rbd": "y", "cat": "xxx", "origin": "us"},
         {"rbd": "z", "cat": "xxx", "origin": "us"},
         {"rbd": "q", "cat": "xxx", "origin": "us"},
         {"rbd": "1", "cat": "xxy", "origin": "us"},
         {"rbd": "2", "cat": "xxy", "origin": "us"}]

print([{"rbd": [i["rbd"] for i in item], "cat": k[0], "origin": k[1]} for k, item in groupby(Input, key=lambda x: (x["cat"], x["origin"]))])

这给了我:

[{'rbd': ['x', 'y', 'z', 'q'], 'cat': 'xxx', 'origin': 'us'}, {'rbd': ['1', '2'], 'cat': 'xxy', 'origin': 'us'}]

可以执行 Itertools.groupby,如此处的一个答案中所述。 另一种方法是将字典列表转换为数据框,然后执行 groupby,然后再转换回字典列表。

df = pd.DataFrame(Input)
df1 = df.groupby(by=['origin', 'cat'])['rbd'].apply(list).reset_index()
df_dicts = df1.to_dict("records")
print(df_dicts)

解决这一挑战的一种方法是通过 defaultdict from the collections 模块:

from collections import defaultdict

d = defaultdict(list)

for entry in Input:
    d[(entry["cat"], entry["origin"])].append(entry["rbd"])

print(d)
defaultdict(list,
        {('xxx', 'us'): ['x', 'y', 'z', 'q'], ('xxy', 'us'): ['1', '2']})


keys = ("rbd", "cat", "origin")

#list comprehension to get final output
[dict(zip(keys, (value, *key))) for key, value in d.items()]

[{'rbd': ['x', 'y', 'z', 'q'], 'cat': 'xxx', 'origin': 'us'},
 {'rbd': ['1', '2'], 'cat': 'xxy', 'origin': 'us'}]