我有一个包含嵌套字典的字典列表,如下所示:
v0 = [ { 'a': 1, 'b': { 'c': 3 } },
{ 'a': 1, 'b': { 'c': 3 }, 'd': 4 },
{ 'a': 1 },
{ 'a': 1, 'b': { 'c': 3 } } ]
如何删除重复的列表元素,结果如下:
v1 = [ { 'a': 1, 'b': { 'c': 3 } },
{ 'a': 1, 'b': { 'c': 3 }, 'd': 4 },
{ 'a': 1 } ]
我不关心秩序,我只想要所有元素的集合。我见过很多类似的问题,但答案只适用于列表中的简单字典,而不是嵌套字典。例如:
v1 = [dict(t) for t in set([tuple(d.items()) for d in v0])]
如果字典没有嵌套,这将有效,但因为它们是,我得到错误“TypeError:unhashable type:'dict'”
答案 0 :(得分:3)
>>> v0 = [ { 'a': 1, 'b': { 'c': 3 } },
... { 'a': 1, 'b': { 'c': 3 }, 'd': 4 },
... { 'a': 1 },
... { 'a': 1, 'b': { 'c': 3 } } ]
>>> out = []
>>> for v in v0:
... if v not in out:
... out.append(v)
...
>>> out
[{'a': 1, 'b': {'c': 3}}, {'a': 1, 'b': {'c': 3}, 'd': 4}, {'a': 1}]
答案 1 :(得分:1)
首先,考虑一个更简单的想法是否足够好。
如果您的词典集不那么大,那么最后一个词典非常简单 - list
已经像set
一样工作,除了每次搜索都是线性的而不是恒定时间。所以,相同的代码将采用二次时间而不是线性,但它会起作用,并且它很简单,所以如果这是可以接受的,那就去做吧。
如果你的词典集很大,那么仍然有一个相对简单的选择:基于树的集合(如blist
或bintrees
中的集合可以在对数时间内搜索)。因此,相同的代码将采用对数线性时间而不是线性 - 这通常足够好 - 并且再次起作用,并且简单易行。
如果即使log-linear太慢,那么你需要一个冻结的dict类型和一个递归冻结函数。但是有一些关于PyPI和ActiveState的实现,比如frozendict
,并且自己编写一个并不太难。
事实上,你已经到了一半。 set([tuple(d.items()] for d in v0])
执行单一级别的冻结,并使用一组元组伪造一个冻结的dict(这对于许多用例不起作用,但对你的用户来说是好的)。所以你只需要递归地做同样的事情。
答案 2 :(得分:0)
如果您对二次算法感到满意,那么
uniq = [x for n, x in enumerate(v0) if v0.index(x) == n]
其他类似
import json
uniq = {json.dumps(x, sort_keys=True):x for x in v0}.values()