假设我有一个字典列表:
[
{'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},
]
这里有一个相当紧凑的解决方案,尽管我怀疑不是特别有效(委婉地说):
>>> ds = [{'id':1,'name':'john', 'age':34},
... {'id':1,'name':'john', 'age':34},
... {'id':2,'name':'hanna', 'age':30}
... ]
>>> map(dict, set(tuple(sorted(d.items())) for d in ds))
[{'age': 30, 'id': 2, 'name': 'hanna'}, {'age': 34, 'id': 1, 'name': 'john'}]
在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+是有效的,因为字典在默认情况下是有序的。
在集合中查找公共元素的通常方法是使用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的答案。
可能有更优雅的解决方案,但我认为最好添加一个更详细的解决方案,使其更容易遵循。这里假设没有唯一键,你有一个简单的k,v结构,并且你使用的python版本保证了列表顺序。这适用于原来的职位。
data_set = [
{'id': 1, 'name': 'john', 'age': 34},
{'id': 1, 'name': 'john', 'age': 34},
{'id': 2, 'name': 'hanna', 'age': 30},
]
# list of keys
keys = [k for k in data_set[0]]
# Create a List of Lists of the values from the data Set
data_set_list = [[v for v in v.values()] for v in data_set]
# Dedupe
new_data_set = []
for lst in data_set_list:
# Check if list exists in new data set
if lst in new_data_set:
print(lst)
continue
# Add list to new data set
new_data_set.append(lst)
# Create dicts
new_data_set = [dict(zip(keys,lst)) for lst in new_data_set]
print(new_data_set)
这是我找到的解决方案:
usedID = []
x = [
{'id':1,'name':'john', 'age':34},
{'id':1,'name':'john', 'age':34},
{'id':2,'name':'hanna', 'age':30},
]
for each in x:
if each['id'] in usedID:
x.remove(each)
else:
usedID.append(each['id'])
print x
基本上你检查ID是否存在于列表中,如果存在,删除字典,如果不存在,将ID追加到列表中