219

辞書のリストがあるとしましょう:

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

22 に答える 22

309

したがって、キーがである一時的なdictを作成しますid。これにより、重複が除外されます。values()dictのはリストになります

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'}]
于 2012-06-18T23:42:23.153 に答える
103

セット内の共通要素だけを見つける通常の方法は、Pythonのsetクラスを使用することです。すべての要素をセットに追加してから、セットをに変換するだけでlist、重複がなくなります。

もちろん、問題は、aにset()はハッシュ可能なエントリしか含めることができず、adictはハッシュ可能ではないということです。

この問題が発生した場合の解決策は、それぞれdictをを表す文字列に変換してdictから、すべての文字列をに追加してset()から、文字列値をaとして読み取り、list()に変換し直すことdictです。

文字列形式での適切な表現dictはJSON形式です。また、PythonにはJSON用の組み込みモジュールがあります(jsonもちろん呼ばれます)。

残りの問題は、aの要素がdict順序付けられていないことです。また、PythonがをJSON文字列に変換するdictと、同等の辞書を表すが同一の文字列ではない2つのJSON文字列を取得する可能性があります。sort_keys=True簡単な解決策は、を呼び出すときに引数を渡すことですjson.dumps()

dict編集:この解決策は、与えられた部分が異なる可能性があることを前提としていました。dict同じ値を持つすべてのものが同じ値を持つ"id"他のすべてのものと一致すると仮定できる場合、これはやり過ぎです。@gnibblerのソリューションは、より速く、より簡単になります。dict"id"

編集:今、アンドレ・リマからのコメントがあり、IDが重複している場合は、全体dictが重複していると見なすのが安全であると明示的に述べています。したがって、この答えはやり過ぎであり、@gnibblerの答えをお勧めします。

于 2012-06-18T23:44:27.623 に答える
60

辞書がすべてのアイテムによって一意に識別されるだけの場合(IDは使用できません)、JSONを使用して回答を使用できます。以下は、JSONを使用しない代替手段であり、すべてのディクショナリ値が不変である限り機能します

[dict(s) for s in set(frozenset(d.items()) for d in L)]
于 2016-07-22T08:00:14.633 に答える
21

これはかなりコンパクトなソリューションですが、(穏やかに言えば)特に効率的ではないと思います。

>>> 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'}]
于 2012-06-18T23:47:40.690 に答える
18

numpyライブラリを使用できます(Python2.xでのみ機能します):

   import numpy as np 

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

Python 3.x(および最近のバージョンのnumpy)で動作させるには、dictの配列を文字列のnumpy配列に変換する必要があります。

list_of_unique_dicts=list(np.unique(np.array(list_of_dicts).astype(str)))
于 2013-11-06T04:25:08.640 に答える
10
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'}]

于 2012-06-18T23:52:59.777 に答える
8

idは重複を検出するのに十分であり、ハッシュ可能であるため、キーとしてidを持っている辞書を介して'emを実行idします。各キーの値は元の辞書です。

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

Python 3ではvalues()、リストを返しません。その式の右側全体をでラップする必要があります。そうすればlist()、式の内容をdictの理解としてより経済的に書くことができます。

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

結果は元の順序と同じではない可能性があることに注意してください。それが要件である場合は、のCollections.OrderedDict代わりにを使用できますdict

余談ですが、最初にasキーを使用する辞書にデータを保持することは非常に理にかなっています。id

于 2012-06-18T23:45:31.063 に答える
6

でできる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パンダのすべての列をチェックします。すべて同じ場合、行は削除されます。

例えば ​​:

2番目の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'}]
于 2019-06-07T01:37:56.670 に答える
4

リスト内のdictの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

それがあなたや他の人が心配しているのを助けることを願っています...

于 2018-06-26T17:11:40.980 に答える
3

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'])
于 2017-09-04T16:14:16.393 に答える
3

ここにはたくさんの答えがあるので、もう1つ追加しましょう。

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)
于 2019-03-13T13:24:10.733 に答える
3

私は試してみるために私のお気に入りを要約しました:

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)
于 2019-12-13T14:33:20.953 に答える
3

Python 3では、単純なトリックですが、一意のフィールド(id)に基づいています。

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

list({ item['id'] : item for item in data}.values())
于 2021-04-02T08:30:30.923 に答える
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オブジェクトとしてエンコードするようにマッピングしていますjson.dumps。これは不変です。set次に、これを使用して、反復可能な一意の不変を生成できます。最後に、を使用して辞書表現に変換し直しますjson.loads。最初は、辞書を一意の形式で配置するためにキーで並べ替える必要があることに注意してください。辞書はデフォルトで順序付けられているため、これはPython3.6以降で有効です。

于 2018-10-02T19:47:00.157 に答える
1

ここに記載されているすべての答えは良いですが、辞書の項目にネストされたリストまたは辞書がある場合、一部の答えでエラーが発生する可能性があるため、簡単な答えを提案します

a = [str(i) for i in a]
a = list(set(a))
a = [eval(i) for i in a]
于 2020-05-27T21:20:57.970 に答える
1

オブジェクトはセットに収まります。dictの代わりにオブジェクトを操作でき、必要に応じて、すべてのセットの挿入がdictのリストに変換されます。例

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]
于 2021-09-25T00:26:39.530 に答える
0

迅速で汚い解決策は、新しいリストを生成するだけです。

sortedlist = []

for item in listwhichneedssorting:
    if item not in sortedlist:
        sortedlist.append(item)
于 2016-09-17T23:58:20.400 に答える
0

私を追加させてください。

  1. {'a':1、'b':2}と{'b':2、'a':1}が異なって扱われないようにターゲットdictを並べ替えます

  2. jsonとして作成

  3. setを介した重複排除(setはdictに適用されないため)

  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]])]
于 2021-09-27T08:08:21.353 に答える
0

辞書に一意のものがない場合は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}]
于 2022-02-18T12:11:11.753 に答える
-1

非常に簡単なオプション:

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
于 2012-06-18T23:48:36.807 に答える
-2

これは、他の部分ほどコンパクトではないという犠牲を払って、メモリオーバーヘッドがほとんどない実装です。

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'}]
于 2012-06-18T23:52:35.937 に答える
-4

これは私が見つけた解決策です:

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をリストに追加します。

于 2012-06-18T23:43:02.130 に答える