在n个dicts列表之间创建一个新的dicts列表?

时间:2014-01-17 04:41:34

标签: python

我有一个未知数量的产品结果列表作为字典条目,它们都具有相同的键。我想生成一个出现在所有旧列表中的新产品列表。

'所有城市都有哪些产品?'

下式给出:

list1 = [{'id': 1, 'name': 'bat', 'price': 20.00}, {'id': 2, 'name': 'ball', 'price': 12.00}, {'id': 3, 'name': 'brick', 'price': 19.00}]
list2 = [{'id': 1, 'name': 'bat', 'price': 18.00}, {'id': 3, 'name': 'brick', 'price': 11.00}, {'id': 2, 'name': 'ball', 'price': 17.00}]
list3 = [{'id': 1, 'name': 'bat', 'price': 16.00}, {'id': 4, 'name': 'boat', 'price': 10.00}, {'id': 3, 'name': 'brick', 'price': 15.00}]
list4 = [{'id': 1, 'name': 'bat', 'price': 14.00}, {'id': 2, 'name': 'ball', 'price': 9.00}, {'id': 3, 'name': 'brick', 'price': 13.00}]
list...

我想要一个dicts列表,其中'id'存在于所有旧列表中:

result_list = [{'id': 1, 'name': 'bat}, {'id': 3, 'name': 'brick}]

对于给定的“id”不是常量的值可以被丢弃,但是给定“id”的值必须在结果列表中。

如果我知道我有多少名单,我可以这样做:

results_list = []
for dict in list1:
    if any(dict['id'] == d['id'] for d in list2):
        if any(dict['id'] == d['id'] for d in list3):
            if any(dict['id'] == d['id'] for d in list4):
                results_list.append(dict)

如果我不知道我有多少个名单,怎么能这样做呢?

1 个答案:

答案 0 :(得分:5)

id放入set s,然后取set s的交叉点。

list1 = [{'id': 1, 'name': 'steve'}, {'id': 2, 'name': 'john'}, {'id': 3, 'name': 'mary'}]
list2 = [{'id': 1, 'name': 'jake'}, {'id': 3, 'name': 'tara'}, {'id': 2, 'name': 'bill'}]
list3 = [{'id': 1, 'name': 'peter'}, {'id': 4, 'name': 'rick'}, {'id': 3, 'name': 'marci'}]
list4 = [{'id': 1, 'name': 'susan'}, {'id': 2, 'name': 'evan'}, {'id': 3, 'name': 'tom'}]
lists = [list1, list2, list3, list4]

sets = [set(x['id'] for x in lst) for lst in lists]
intersection = set.intersection(*sets)
print(intersection)

结果:

{1, 3}

请注意,我们调用类方法set.intersection而不是实例方法set().intersection,因为后者将其参数与空集set()交叉,当然还有任何空集都是空的。

如果你想把它变成一个dicts列表,你可以这样做:

result = [{'id': i, 'name': None} for i in intersection]
print(result)

结果:

[{'id': 1, 'name': None}, {'id': 3, 'name': None}]

现在,如果您还想保留对于给定id的所有实例都相同的属性,您将要执行以下操作:

list1 = [{'id': 1, 'name': 'bat', 'price': 20.00}, {'id': 2, 'name': 'ball', 'price': 12.00}, {'id': 3, 'name': 'brick', 'price': 19.00}]
list2 = [{'id': 1, 'name': 'bat', 'price': 18.00}, {'id': 3, 'name': 'brick', 'price': 11.00}, {'id': 2, 'name': 'ball', 'price': 17.00}]
list3 = [{'id': 1, 'name': 'bat', 'price': 16.00}, {'id': 4, 'name': 'boat', 'price': 10.00}, {'id': 3, 'name': 'brick', 'price': 15.00}]
list4 = [{'id': 1, 'name': 'bat', 'price': 14.00}, {'id': 2, 'name': 'ball', 'price': 9.00}, {'id': 3, 'name': 'brick', 'price': 13.00}]
lists = [list1, list2, list3, list4]

sets = [set(x['id'] for x in lst) for lst in lists]
intersection = set.intersection(*sets)

all_keys = set(lists[0][0].keys())
result = []
for ident in intersection:
    res = [dic for lst in lists
               for dic in lst
           if dic['id'] == ident]
    replicated_keys = []
    for key in all_keys:
        if len(set(dic[key] for dic in res)) == 1:
            replicated_keys.append(key)
    result.append({key: res[0][key] for key in replicated_keys})
print(result)

结果:

[{'id': 1, 'name': 'bat'}, {'id': 3, 'name': 'brick'}]

我们在这里做的是:

  • 查看id中的每个intersection并抓住与id对应的每个字典。
  • 查找所有这些键中具有相同值的键(其中一个键保证为id)。
  • 将这些键值对放入result

此代码假定:

  • list1, list2, ...中的每个字典都有相同的键。如果这个假设是错误的,请告诉我 - 它不应该让人放松。