唯一字典列表

假设我有一个字典列表:

[
{'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},
]
190488 次浏览
因此,创建一个临时字典,键为id。这将过滤掉重复的内容。 字典的values()将是list

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

这是我找到的解决方案:

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

在集合中查找公共元素的通常方法是使用Python的set类。只需将所有元素添加到集合中,然后将集合转换为list,然后嘭的一遍,重复的元素就消失了。

当然,问题是set()只能包含可哈希的项,而dict是不可哈希的。

如果我遇到这个问题,我的解决方案是将每个dict转换为表示dict的字符串,然后将所有字符串添加到set()中,然后将字符串值作为list()读取并转换回dict

字符串形式的dict的良好表示是JSON格式。Python有一个内置的JSON模块(当然叫做json)。

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

编辑:这个解决方案假设给定的dict可以有任何不同的部分。如果我们可以假设每个具有相同"id"值的dict将匹配其他具有相同"id"值的dict,那么这是过度的;@gnibbler的解决方案更快更简单。

编辑:现在有一个来自André Lima的评论明确指出,如果ID是一个副本,则可以安全地假设整个dict是一个副本。所以这个答案太夸张了,我推荐@gnibbler的答案。

由于id足以检测重复项,并且id是可哈希的:在以id为键的字典中运行它们。每个键的值都是原始字典。

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

在Python 3中,values()不返回列表;你需要在list()中包装整个表达式的右边,并且你可以将表达式的部分更经济地写成字典理解:

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

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

顺便说一句,在使用id作为键开始的字典中,只保持数据可能很有意义。

这里有一个相当紧凑的解决方案,尽管我怀疑不是特别有效(委婉地说):

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

非常简单的选择:

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

这里有一个内存开销很小的实现,代价是不像其他实现那样紧凑。

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

输出:

[{“年龄”:34岁“id”:1、“名称”:“约翰”},{“id”:“年龄”:30日2时,“名字”:“汉娜”}]

你可以使用numpy库(适用于Python2。x只):

   import numpy as np


list_of_unique_dicts=list(np.unique(np.array(list_of_dicts)))

让它在Python 3中工作。X(以及numpy的最新版本),您需要将字典数组转换为numpy字符串数组,例如。

list_of_unique_dicts=list(np.unique(np.array(list_of_dicts).astype(str)))

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

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

一个快速的解决方案是生成一个新列表。

sortedlist = []


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

扩展John La Rooy (唯一字典的列表)的答案,使其更加灵活:

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

我不知道你是否只希望列表中dicts的id是唯一的,但如果目标是有一组dict,其中所有键的值都是唯一的。你应该像这样使用元组键:

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

希望它能帮助你或其他有顾虑的人....

在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.dumps来将字典编码为json对象,这是不可变的。set可用于生成独特的不可变对象的迭代对象。最后,我们使用json.loads转换回字典表示。注意,一开始,必须按键排序才能以唯一的形式排列字典。这对于Python 3.6+是有效的,因为字典在默认情况下是有序的。

这里有很多答案,所以让我再补充一个:

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)

我们可以用pandas

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_duplicates将检查pandas中的所有列,如果所有列都相同,则删除该行。

例如:

如果将第二个dict名称从约翰< em > < / em >更改为彼得< em > < / em >

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

我总结了我最喜欢的尝试:

< a href = " https://repl。它/ @SmaMa Python-List-of-unique-dictionaries noreferrer“rel = > https://repl.it/@SmaMa Python-List-of-unique-dictionaries < / >

# ----------------------------------------------
# Setup
# ----------------------------------------------


myList = [
{"id":"1", "lala": "value_1"},
{"id": "2", "lala": "value_2"},
{"id": "2", "lala": "value_2"},
{"id": "3", "lala": "value_3"}
]
print("myList:", myList)


# -----------------------------------------------
# Option 1 if objects has an unique identifier
# -----------------------------------------------


myUniqueList = list({myObject['id']:myObject for myObject in myList}.values())
print("myUniqueList:", myUniqueList)


# -----------------------------------------------
# Option 2 if uniquely identified by whole object
# -----------------------------------------------


myUniqueSet = [dict(s) for s in set(frozenset(myObject.items()) for myObject in myList)]
print("myUniqueSet:", myUniqueSet)


# -----------------------------------------------
# Option 3 for hashable objects (not dicts)
# -----------------------------------------------


myHashableObjects = list(set(["1", "2", "2", "3"]))
print("myHashAbleList:", myHashableObjects)

这里提到的所有答案都很好,但在一些答案中,如果字典项有嵌套的列表或字典,就会面临错误,所以我建议简单的答案

a = [str(i) for i in a]
a = list(set(a))
a = [eval(i) for i in a]

在python 3中,简单的技巧,但基于唯一字段(id):

data = [ {'id': 1}, {'id': 1}]


list({ item['id'] : item for item in data}.values())

对象可以放入集合中。您可以使用对象而不是字典,如果需要,在所有set插入后转换回字典列表。例子

class Person:
def __init__(self, id, age, name):
self.id = id
self.age = age
self.name = name


my_set = {Person(id=2, age=3, name='Jhon')}


my_set.add(Person(id=3, age=34, name='Guy'))


my_set.add({Person(id=2, age=3, name='Jhon')})


# if needed convert to list of dicts
list_of_dict = [{'id': obj.id,
'name': obj.name,
'age': obj.age} for obj in my_set]

让我加上我的。

  1. 排序目标字典,以便{'a': 1, 'b': 2}和{'b': 2, 'a': 1}不会被区别对待

  2. 将其作为json

  3. 通过set重复数据删除(因为set不适用于dicts)

  4. ,通过json.loads将其转换为dict

import json


[json.loads(i) for i in set([json.dumps(i) for i in [dict(sorted(i.items())) for i in target_dict]])]

如果字典中有 -唯一的id,那么我将保持它的简单,并定义如下函数:

def unique(sequence):
result = []
for item in sequence:
if item not in result:
result.append(item)
return result

这种方法的优点是,您可以为任何可比较的对象重用此函数。它使您的代码非常可读,适用于所有现代版本的Python,保持字典中的顺序,并且与其他选项相比速度也很快。

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