假设我有一个字典列表:
[
{'id': 1, 'name': 'john', 'age': 34},
{'id': 1, 'name': 'john', 'age': 34},
{'id': 2, 'name': 'hanna', 'age': 30},
]
如何获得唯一字典的列表(删除重复项)?
[
{'id': 1, 'name': 'john', 'age': 34},
{'id': 2, 'name': 'hanna', 'age': 30},
]
非常简单的选择:
L = [
{'id':1,'name':'john', 'age':34},
{'id':1,'name':'john', 'age':34},
{'id':2,'name':'hanna', 'age':30},
]
D = dict()
for l in L: D[l['id']] = l
output = list(D.values())
print output
在python 3.6+(我已经测试过了)中,只需使用:
import json
#Toy example, but will also work for your case
myListOfDicts = [{'a':1,'b':2},{'a':1,'b':2},{'a':1,'b':3}]
#Start by sorting each dictionary by keys
myListOfDictsSorted = [sorted(d.items()) for d in myListOfDicts]
#Using json methods with set() to get unique dict
myListOfUniqueDicts = list(map(json.loads,set(map(json.dumps, myListOfDictsSorted))))
print(myListOfUniqueDicts)
解释:我们正在映射json。转储将字典编码为json对象,这是不可变的。Set可用于生成包含唯一不可变对象的迭代对象。最后,我们使用json.loads转换回字典表示。注意,一开始,必须按键排序才能以唯一的形式排列字典。这对于Python 3.6+是有效的,因为字典在默认情况下是有序的。
我们可以用熊猫
import pandas as pd
yourdict=pd.DataFrame(L).drop_duplicates().to_dict('r')
Out[293]: [{'age': 34, 'id': 1, 'name': 'john'}, {'age': 30, 'id': 2, 'name': 'hanna'}]
注意与接受答案略有不同。
drop_duplicate将检查pandas中的所有列,如果都相同则删除该行。
例如:
如果我们把第二个字典的名字从约翰改为彼得
L=[
{'id': 1, 'name': 'john', 'age': 34},
{'id': 1, 'name': 'peter', 'age': 34},
{'id': 2, 'name': 'hanna', 'age': 30},
]
pd.DataFrame(L).drop_duplicates().to_dict('r')
Out[295]:
[{'age': 34, 'id': 1, 'name': 'john'},
{'age': 34, 'id': 1, 'name': 'peter'},# here will still keeping the dict in the out put
{'age': 30, 'id': 2, 'name': 'hanna'}]
在集合中查找公共元素的通常方法是使用Python的set类。只需将所有元素添加到集合中,然后将集合转换为列表,然后重复的元素就消失了。
当然,问题在于set()只能包含可哈希的条目,而dict是不可哈希的。
如果我遇到这个问题,我的解决方案是将每个dict转换为表示该dict的字符串,然后将所有字符串添加到set()中,然后将字符串值作为列表()读取并转换回dict。
字符串形式的字典的一个很好的表示是JSON格式。Python有一个内置的JSON模块(当然叫做JSON)。
剩下的问题是字典中的元素没有顺序,当Python将字典转换为JSON字符串时,您可能会得到两个表示等效字典的JSON字符串,但它们不是相同的字符串。简单的解决方案是在调用json.dumps()时传递参数sort_keys=True。
编辑:这个解决方案是假设一个给定的字典可以有任何不同的部分。如果我们可以假设每个具有相同“id”值的dict将匹配其他具有相同“id”值的dict,那么这是过度的;@gnibbler的解决方案更快更简单。
编辑:现在有一个来自André Lima的评论明确表示,如果ID是一个副本,那么可以安全地假设整个字典是一个副本。所以这个答案太夸张了,我推荐@gnibbler的答案。
这里有很多答案,所以让我再补充一个:
import json
from typing import List
def dedup_dicts(items: List[dict]):
dedupped = [ json.loads(i) for i in set(json.dumps(item, sort_keys=True) for item in items)]
return dedupped
items = [
{'id': 1, 'name': 'john', 'age': 34},
{'id': 1, 'name': 'john', 'age': 34},
{'id': 2, 'name': 'hanna', 'age': 30},
]
dedup_dicts(items)
这里有一个内存开销很小的实现,代价是不像其他实现那样紧凑。
values = [ {'id':2,'name':'hanna', 'age':30},
{'id':1,'name':'john', 'age':34},
{'id':1,'name':'john', 'age':34},
{'id':2,'name':'hanna', 'age':30},
{'id':1,'name':'john', 'age':34},]
count = {}
index = 0
while index < len(values):
if values[index]['id'] in count:
del values[index]
else:
count[values[index]['id']] = 1
index += 1
输出:
[{'age': 30, 'id': 2, 'name': 'hanna'}, {'age': 34, 'id': 1, 'name': 'john'}]