Python – 独特词典的列表

比方说,我有一个字典列表:

[ {'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}, ] 

任何人都可以帮助我以最有效的方式来实现这个在Python?

因此,使用id作为临时字典。 这将筛选出重复项。 字典的values()将成为列表

在Python2.7

 >>> L=[ ... {'id':1,'name':'john', 'age':34}, ... {'id':1,'name':'john', 'age':34}, ... {'id':2,'name':'hanna', 'age':30}, ... ] >>> {v['id']:v for v in L}.values() [{'age': 34, 'id': 1, 'name': 'john'}, {'age': 30, 'id': 2, 'name': 'hanna'}] 

在Python3中

 >>> L=[ ... {'id':1,'name':'john', 'age':34}, ... {'id':1,'name':'john', 'age':34}, ... {'id':2,'name':'hanna', 'age':30}, ... ] >>> list({v['id']:v for v in L}.values()) [{'age': 34, 'id': 1, 'name': 'john'}, {'age': 30, 'id': 2, 'name': 'hanna'}] 

在Python2.5 / 2.6中

 >>> L=[ ... {'id':1,'name':'john', 'age':34}, ... {'id':1,'name':'john', 'age':34}, ... {'id':2,'name':'hanna', 'age':30}, ... ] >>> dict((v['id'],v) for v in L).values() [{'age': 34, 'id': 1, 'name': 'john'}, {'age': 30, 'id': 2, 'name': 'hanna'}] 

寻找集合中常见元素的常用方法是使用Python的set类。 只需将所有元素添加到该集合,然后将该集合转换为list ,并且重复的bam消失了。

当然,问题是一个set()只能包含可sorting的条目,而一个dict是不可散列的。

如果我遇到了这个问题,我的解决scheme是将每个dict转换为一个代表dict的string,然后将所有string添加到一个set()然后将string值读出为list()并将其转换为dict

stringforms的dict一个很好的代表是JSON格式。 而Python有一个JSON的内置模块(当然称为json )。

剩下的问题是, dict中的元素没有sorting,当Python将dict转换为JSONstring时,可能会得到两个JSONstring表示等效字典,但不是相同的string。 简单的解决方法是在调用json.dumps()时传递参数sort_keys=True

编辑:这个解决scheme假设一个给定的dict可以有任何不同的部分。 如果我们可以认为每个具有相同"id"值的dict都会匹配具有相同"id"值的其他dict ,那么这是过度的; @ gnibbler的解决scheme会更快,更容易。

编辑:现在有来自AndréLima的意见,明确表示如果ID是重复的,可以安全地假定整个dict是重复的。 所以这个答案是矫枉过正,我推荐@ gnibbler的答案。

您可以使用numpy库(仅适用于Python2.x):

  import numpy as np list_of_unique_dicts=list(np.unique(np.array(list_of_dicts))) 

这是一个相当紧凑的解决scheme,虽然我怀疑不是特别有效(说得温和):

 >>> 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'}] 

由于id足够用于检测重复,并且id是可散列的:通过以id为关键字的字典运行em。 每个键的值是原始字典。

 deduped_dicts = dict((item["id"], item) for item in list_of_dicts).values() 

在Python 3中, values()不返回一个列表; 你需要将整个expression式的右边部分包含在list() ,并且可以更经济地编写expression式的内容作为dict理解:

 deduped_dicts = list({item["id"]: item for item in list_of_dicts}.values()) 

请注意,结果可能不会与原来的顺序相同。 如果这是一个要求,你可以使用Collections.OrderedDict而不是一个dict

顺便说一下, 数据保存在使用id作为关键字的字典中可能会很有意义。

 a = [ {'id':1,'name':'john', 'age':34}, {'id':1,'name':'john', 'age':34}, {'id':2,'name':'hanna', 'age':30}, ] b = {x['id']:x for x in a}.values() print(b) 

输出:

'{'age':34,'id':1,'name':'john'},{'age':30,'id':2,'name':'hanna'}]

如果字典只能由所有项目唯一标识(ID不可用),则可以使用JSON使用答案。 以下是不使用JSON的替代方法,只要所有的字典值都是不变的,就可以工作

 [dict(s) for s in set(frozenset(d.items()) for d in L)] 

非常简单的选项:

 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 

下面是一个很less的内存开销的实现,代价是不像其他的那样紧凑。

 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'}] 

这是我find的解决scheme:

 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附加到列表中

一个快速而肮脏的解决scheme就是生成一个新的列表。

 sortedlist = [] for item in listwhichneedssorting: if item not in sortedlist: sortedlist.append(item) 

在John La Rooy( Python – 独特词典列表 )上进行扩展,使其更加灵活:

 def dedup_dict_list(list_of_dicts: list, columns: list) -> list: return list({''.join(row[column] for column in columns): row for row in list_of_dicts}.values()) 

调用函数:

 sorted_list_of_dicts = dedup_dict_list( unsorted_list_of_dicts, ['id', 'name'])