Python - 独特词典列表

Lim*_*aaf 135 python dictionary

假设我有一个词典列表:

[
    {'id': 1, 'name': 'john', 'age': 34},
    {'id': 1, 'name': 'john', 'age': 34},
    {'id': 2, 'name': 'hanna', 'age': 30},
]
Run Code Online (Sandbox Code Playgroud)

我需要获取一个唯一的字典列表(删除重复的字典):

[
    {'id': 1, 'name': 'john', 'age': 34},
    {'id': 2, 'name': 'hanna', 'age': 30},
]
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮助我在Python中实现这一目标的最有效方法吗?

Joh*_*ooy 214

所以制作一个临时词典,关键是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'}]
Run Code Online (Sandbox Code Playgroud)

在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'}]
Run Code Online (Sandbox Code Playgroud)

在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'}]
Run Code Online (Sandbox Code Playgroud)

  • @JorgeVidinha,你可以使用元组作为字典键`{(v ['flight'],v ['lon'],v ['lat']):v for v in stream} .values()` (4认同)
  • 这实际上并没有删除相同字典的重复项(其中 dict1 == dict2 返回 true)。仅当您确定了要比较的密钥时,该解决方案才有效。 (3认同)
  • `v['id']:v for v in L` 创建新字典,其中 ids 作为键,整个字典作为值。默认情况下,字典中的键是唯一的,因此如果将具有相同 id 的字典添加到这个新字典中,它将覆盖以前具有相同 id 的字典。`.values()` 返回一个视图对象,该对象显示字典中所有值的列表 - 这里是整个唯一(按 id)字典的列表。而 `list(...)` 只是将返回视图的 `dict_values` 对象转换为简单的 Python `list`。 (3认同)
  • @JorgeVidinha 假设每个都可以转换为 str(或 unicode),试试这个:`{str(v['flight'])+':'+str(v['lon'])+','+str(v ['lat']): v for v in stream}.values()` 这只是根据您的值创建一个唯一键。喜欢`'MH370:-21.474370,86.325589'` (2认同)
  • 如果您需要考虑所有值而不仅仅是 ID,您可以使用 ```list({str(i):i for i in L}.values())``` 这里我们使用 str(i) 创建一个唯一的表示用于过滤重复项的字典的字符串。 (2认同)

ste*_*eha 70

找到集合中常见元素的常用方法是使用Python的set类.只需将所有元素添加到集合中,然后将集合转换为a list,bam重复项就会消失.

当然,问题是a set()只能包含hashable条目,而a dict不可清除.

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

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

剩下的问题是a中的元素dict没有排序,当Python将其转换dict为JSON字符串时,您可能会得到两个代表等效字典但不是相同字符串的JSON字符串.简单的解决方案是sort_keys=True在您打电话时传递参数json.dumps().

编辑:这个解决方案假设给定的dict任何部分可能有所不同.如果我们可以假设,每一个dict具有相同"id"的值将匹配所有其它dict具有相同"id"的值,那么这是矫枉过正; @ gnibbler的解决方案将更快更容易.

编辑:现在AndréLima明确表示,如果ID是重复的,可以安全地假设整个dict是重复的.所以这个答案是矫枉过正的,我建议@ gnibbler的回答.

  • 这对我有帮助,因为我的字典没有密钥,并且只有所有条目唯一标识.谢谢! (5认同)
  • 虽然在这种特殊情况下给出了 ID,但这仍然是一个很好的答案! (3认同)
  • 简而言之,这个解决方案说明了为什么您想要设计解决方案的一个很好的规范示例...即,如果您有一个唯一的 id...那么您可以有效地访问数据...如果您很懒如果没有 id 那么你的数据访问会更加昂贵。 (2认同)

bub*_*ble 18

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

   import numpy as np 

   list_of_unique_dicts=list(np.unique(np.array(list_of_dicts)))
Run Code Online (Sandbox Code Playgroud)

  • 在Python 3.5中执行此操作时,获取错误`TypeError:unorderable types:dict()> dict()`. (11认同)

Sin*_*ina 18

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

[dict(s) for s in set(frozenset(d.items()) for d in L)]
Run Code Online (Sandbox Code Playgroud)

  • 到山顶你必须去。 (2认同)

Gre*_* E. 16

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

>>> 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'}]
Run Code Online (Sandbox Code Playgroud)

  • 在Python 3中使用`list()`进行`map()`调用以获取列表,否则它是一个`map`对象. (3认同)

WeN*_*Ben 8

我们可以做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'}]
Run Code Online (Sandbox Code Playgroud)

请注意与接受答案略有不同。

drop_duplicates将检查 pandas 中的所有列,如果全部相同则该行将被删除。

例如 :

如果我们将第二个dict名字从约翰改为彼得

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'}]
Run Code Online (Sandbox Code Playgroud)


小智 8

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

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

list({ item['id'] : item for item in data}.values())
Run Code Online (Sandbox Code Playgroud)


kin*_*all 7

因为id它足以检测重复项,并且id可以清除:通过具有id关键字的字典运行它们.每个键的值是原始字典.

deduped_dicts = dict((item["id"], item) for item in list_of_dicts).values()
Run Code Online (Sandbox Code Playgroud)

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

deduped_dicts = list({item["id"]: item for item in list_of_dicts}.values())
Run Code Online (Sandbox Code Playgroud)

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

顺便说一下,数据保存在使用idas键开头的字典中可能很有意义.


Sma*_* Ma 7

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

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)
Run Code Online (Sandbox Code Playgroud)


Yus*_*f X 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)
Run Code Online (Sandbox Code Playgroud)

输出:

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

  • b = {x['id']:[y for y in a if y['id'] == x['id'] ] for x in a} 是将它们分组在一起的一种方法。 (2认同)

mon*_*kut 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)
Run Code Online (Sandbox Code Playgroud)