我们说我有一个词典列表:
[
{'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中实现这一目标吗?
答案 0 :(得分:190)
所以制作一个临时字典,密钥为id
。这会过滤掉重复项。
dict的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'}]
答案 1 :(得分:63)
查找集合中常见元素的常用方法是使用Python的set
类。只需将所有元素添加到集合中,然后将集合转换为list
,然后重复项就会消失。
问题当然是set()
只能包含可输入的条目,并且dict
不可清除。
如果我遇到此问题,我的解决方案是将每个dict
转换为代表dict
的字符串,然后将所有字符串添加到set()
然后读出字符串值为list()
并转换回dict
。
字符串形式的dict
的良好表示是JSON格式。 Python有一个内置的JSON模块(当然称为json
)。
剩下的问题是dict
中的元素没有排序,当Python将dict
转换为JSON字符串时,您可能会得到两个表示等效字典但不相同的JSON字符串字符串。简单的解决方案是在调用sort_keys=True
时传递参数json.dumps()
。
编辑:此解决方案假设给定dict
可能有任何不同的部分。如果我们可以假设具有相同dict
值的每个"id"
将与具有相同dict
值的所有其他"id"
匹配,那么这是过度的; @ gnibbler的解决方案将更快更容易。
编辑:现在AndréLima明确表示,如果ID是重复的,可以安全地假设整个dict
是重复的。所以这个答案是矫枉过正的,我建议@ gnibbler回答。
答案 2 :(得分:17)
您可以使用numpy库(仅适用于Python2.x):
import numpy as np
list_of_unique_dicts=list(np.unique(np.array(list_of_dicts)))
要使它与Python 3.x(以及numpy的最新版本)一起使用,您需要将dicts数组转换为numpy字符串数组,例如
list_of_unique_dicts=list(np.unique(np.array(list_of_dicts).astype(str)))
答案 3 :(得分:14)
如果词典仅由所有项目唯一标识(ID不可用),您可以使用JSON使用答案。以下是不使用JSON的替代方法,只要所有字典值都是不可变的
,它就会起作用[dict(s) for s in set(frozenset(d.items()) for d in L)]
答案 4 :(得分:13)
这是一个相当紧凑的解决方案,但我怀疑不是特别有效(温和地说):
>>> 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'}]
答案 5 :(得分:7)
由于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
作为键开头的词典中可能很有意义。
答案 6 :(得分:6)
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'}]
答案 7 :(得分:3)
扩展John La Rooy(Python - List of unique dictionaries)的答案,使其更灵活:
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'])
答案 8 :(得分:1)
在python 3中,简单的技巧,但基于唯一字段(id):
data = [ {'id': 1}, {'id': 1}]
list({ item['id'] : item for item in data}.values())
答案 9 :(得分:1)
我们可以使用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
将检查熊猫中的所有列,如果全部相同,则将删除该行。
例如:
如果我们将第二个dict
名称从 john 更改为 peter
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'}]
答案 10 :(得分:1)
在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+有效,因为默认情况下字典是顺序排列的。
答案 11 :(得分:1)
快速而肮脏的解决方案就是生成一个新列表。
sortedlist = []
for item in listwhichneedssorting:
if item not in sortedlist:
sortedlist.append(item)
答案 12 :(得分:0)
我不知道您是否只希望列表中的字典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
希望它可以帮助您或其他有问题的人。...
答案 13 :(得分:0)
这里有很多答案,所以让我添加另一个:
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)
答案 14 :(得分:0)
非常简单的选择:
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
答案 15 :(得分:0)
我总结了我的最爱以尝试:
{{3}}
# ----------------------------------------------
# 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)
答案 16 :(得分:0)
这里提到的所有答案都很好,但是在某些答案中,如果字典项具有嵌套列表或字典,则可能会遇到错误,因此我提出了简单答案
a = [str(i) for i in a]
a = list(set(a))
a = [eval(i) for i in a]
答案 17 :(得分:-1)
这是一个实现内存开销很小的实现,代价是不像其他部分那么紧凑。
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'}]
答案 18 :(得分:-3)
这是我找到的解决方案:
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附加到列表中