Python - 根据另一个对象列表的计数创建一个对象列表

Python - Create a list of objects based on counts of another list of objects

我有一个对象列表,我想创建另一个项目列表,但按“名称”和两个字段分组,这两个字段是特定实例类型的实例数。 我有这个:

result = [
    {"Name": "Foo", "Type": "A", "RandomColumn1": "1"},
    {"Name": "Bar", "Type": "B", "RandomColumn2": "2"},
    {"Name": "Foo", "Type": "A", "RandomColumn3": "3"},
    {"Name": "Bar", "Type": "A", "RandomColumn4": "4"},
    {"Name": "Foo", "Type": "B", "RandomColumn5": "5"},
]

我正在尝试计算不同“类型”列的数量,同时丢弃任何其他列 - 在本例中为 RandomColumnX。

我要上面这样出来:

[{"Name": "Foo", "A": 2, "B": 1}, {"Name": "Bar", "A": 1, "B": 1}]

我试过这样做:


group_requests = [{
    "Name": key,
    "A": len([d for d in list(value) if d.get('Type') == 'A']),
    "B": len([y for y in list(value) if y['Type'] == 'B']),
} for key, value in groupby(result, key=lambda x: x['Name'])]

但是,它不计算“B”列中的值,并且此键的计数始终为 0。

有人可以帮我吗?

错误一. 为了让 itertools.groupby 工作,你的输入迭代需要已经在相同的键函数上排序。

result = sorted(result, key=lambda x: x["Name"])

错误2. 返回的组即 value 本身就是一个迭代器,因此您需要保存输出以便多次迭代它。

group_requests = []
for key, value in itertools.groupby(result, key=lambda x: x["Name"]):
    <b>value = list(value)  # save the output</b>
    temp = {
        "Name": key,
        "A": len([d for d in value if d.get("Type") == "A"]),
        "B": len([y for y in value if y["Type"] == "B"]),
    }
    group_requests.append(temp)

如果有人想要没有列表理解。可以这样实现

from collections import defaultdict

result = [{"Name": "Foo", "Type": "A", "RandomColumn1": "1"},
    {"Name": "Bar", "Type": "B", "RandomColumn2": "2"},
    {"Name": "Foo", "Type": "A", "RandomColumn3": "3"},
    {"Name": "Bar", "Type": "A", "RandomColumn4": "4"},
    {"Name": "Foo", "Type": "B", "RandomColumn5": "5"}]

group_requests = []

counterA = defaultdict(int)
counterB = defaultdict(int)
names = set()

for val in result:
    name = val["Name"]
    type = val["Type"]
    
    if type == "A":
        counterA[name] += 1
    else:
        counterB[name] += 1

    names.add(name)

for name in names:
    group_requests.append({
        "Name": name,
        "A": counterA[name],
        "B": counterB[name]
    })

print(group_requests)