按所有键唯一的键排序列表

时间:2017-06-19 09:56:33

标签: python list sorting dictionary

用这个把头发拉出来。

我有一个字典列表,每个唯一条目没有唯一的主ID键(字典是动态构建的):

dicts = [{'firstname': 'john', 'lastname': 'doe', 'code': 'crumpets'},
         {'firstname': 'john', 'lastname': 'roe', 'code': 'roe'},
         {'firstname': 'john', 'lastname': 'doe', 'code': 'crumpets'},
         {'firstname': 'thom', 'lastname': 'doe', 'code': 'crumpets'},
]

如何删除列表中的任何重复{}的字典列表?因此,我需要检查所有三个字典键是否与列表中的另一个匹配...然后如果满足该检查则从dict丢弃该字典键。

所以,对于我上面的例子,第一个和第三个"条目"需要删除,因为它们是重复的。

3 个答案:

答案 0 :(得分:5)

你使用dicts中的create frozensets并将它们放在一个集合中以删除dupes:

dcts = [dict(d) for d in set(frozenset(d.items()) for d in dcts)]
print(dcts)
[{'code': 'roe', 'firstname': 'john', 'lastname': 'roe'},
 {'code': 'crumpets', 'firstname': 'thom', 'lastname': 'doe'},
 {'code': 'crumpets', 'firstname': 'john', 'lastname': 'doe'}]

如果您选择删除重复项的所有条目,则可以使用计数器:

from collections import Counter

dcts = [dict(d) for d, cnt in Counter(frozenset(d.items()) for d in dcts).items() 
                                                                      if cnt==1]
print(dcts)
[{'code': 'roe', 'firstname': 'john', 'lastname': 'roe'},
 {'code': 'crumpets', 'firstname': 'thom', 'lastname': 'doe'}]

答案 1 :(得分:2)

删除不可清除元素列表中的重复项要求您在运行时使其可以清除:

def remove_duplicated_dicts(elements):
    seen = set()
    result = []
    for element in elements:
        element_as_tuple = tuple(element.items())
        if element_as_tuple not in seen:
            seen.add(element_as_tuple)
            result.append(element)
    return result

d = [{'firstname': 'john', 'lastname': 'doe', 'code': "crumpets"},
        {'firstname': 'john', 'lastname': 'roe', 'code': "roe"},
        {'firstname': 'john', 'lastname': 'doe', 'code': "crumpets"},
        {'firstname': 'thom', 'lastname': 'doe', 'code': "crumpets"},
]

print(remove_duplicated_dicts(d))

<强> PS。

与Moses Koledoye接受的答案(截至2017-06-19 13:00:00)有明显不同之处:

  • 保存原始列表顺序;
  • 更快的转化次数:dict -> tuple而不是dict -> frozendict -> dict(带上一粒盐:我没有做过基准测试)。

答案 2 :(得分:1)

鉴于字典的值可以播放,我们可以生成自己的 uniqness 过滤器:

def uniq(iterable, key = lambda x:x):
    keys = set()
    for item in iterable:
        ky = key(item)
        if ky not in keys:
            yield item
            keys.add(ky)

然后我们可以简单地使用过滤器,例如:

list(uniq(dicts,key=lambda x:(x['firstname'],x['lastname'],x['code'])))

过滤器保持原始顺序,并且 - 对于此示例 - 将生成:

>>> list(uniq(dicts,key=lambda x:(x['firstname'],x['lastname'],x['code'])))
[{'code': 'crumpets', 'firstname': 'john', 'lastname': 'doe'},
 {'code': 'roe', 'firstname': 'john', 'lastname': 'roe'},
 {'code': 'crumpets', 'firstname': 'thom', 'lastname': 'doe'}]