在Python中删除重复的列表中的字典
我有一个列表的列表,我想删除具有相同的键和值对的字典。
对于此列表: [{'a': 123}, {'b': 123}, {'a': 123}]
我想返回这个: [{'a': 123}, {'b': 123}]
另一个例子:
对于这个列表: [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}, {'a': 123, 'b': 1234}]
我想返回这个: [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}]
尝试这个:
[dict(t) for t in set([tuple(d.items()) for d in l])]
该策略是将字典列表转换为元组列表,其中元组包含字典的项目。 由于元组可以被散列,所以你可以使用set
来删除重复元素,然后用字典从元组中重新创builddict
。
哪里:
-
l
是原始列表 -
d
是列表中的一个字典 -
t
是从字典中创build的元组之一
编辑:如果你想保持sorting,上面的单行不会工作,因为set
不会这样做。 但是,用几行代码,你也可以这样做:
l = [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}, {'a': 123, 'b': 1234}] seen = set() new_l = [] for d in l: t = tuple(d.items()) if t not in seen: seen.add(t) new_l.append(d) print new_l
示例输出:
[{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}]
注意:正如@alexis指出的那样,可能发生两个具有相同键和值的字典不会产生相同的元组。 如果他们通过不同的添加/删除键历史logging可能会发生这种情况。 如果这是你的问题的情况下,然后考虑按照他的build议sortingd.items()
。
另一个基于列表parsing的单行:
>>> d = [{'a': 123}, {'b': 123}, {'a': 123}] >>> [i for n, i in enumerate(d) if i not in d[n + 1:]] [{'b': 123}, {'a': 123}]
在这里,因为我们可以使用dict
比较,所以我们只保留不在初始列表的其余部分的元素(这个概念只能通过索引n
访问,因此使用enumerate
)。
如果您使用嵌套字典(如反序列化的JSON对象),则其他答案将不起作用。 对于这种情况下,你可以使用:
import json set_of_jsons = {json.dumps(d, sort_keys=True) for d in X} X = [json.loads(t) for t in set_of_jsons]
如果你想保留订单,那么你可以做
from collections import OrderedDict print OrderedDict((frozenset(item.items()),item) for item in data).values() # [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}]
如果顺序没有关系,那么你可以做
print {frozenset(item.items()):item for item in data}.values() # [{'a': 3222, 'b': 1234}, {'a': 123, 'b': 1234}]
有时旧式循环仍然有用。 这个代码比jcollado的长一点,但是很容易阅读:
a = [{'a': 123}, {'b': 123}, {'a': 123}] b = [] for i in range(0, len(a)) if a[i] not in a[i+1:] b.append(a[i])
你可以使用一个集合,但是你需要把这些字典变成一个可排列的types。
seq = [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}, {'a': 123, 'b': 1234}] unique = set() for d in seq: t = tuple(d.iteritems()) unique.add(t)
独特的现在等于
set([(('a', 3222), ('b', 1234)), (('a', 123), ('b', 1234))])
为了得到答案:
[dict(x) for x in unique]