6
votes

Comment supprimer des objets de dictionnaire dupliqués d'une liste de dictionnaires

Je souhaite supprimer les objets de dictionnaire dupliqués d'une liste de dictionnaires. Je ne veux pas de l'élément dict qui a le même élément «plaque» avec un autre élément dict dans la liste. Je ne le veux qu'une seule fois.

[

    {
        'plate': "01",
        'confidence' : "80"
    },

    {
        'plate': "02",
        'confidence' : "91"
    },

    {
        'plate': "02",
        'confidence' : "91"
    },
]

Ma sortie devrait être comme ceci:

def filter(datalist):
    previous = ""
    for data in datalist:
        current  = data['plate']
        if current is previous:
            datalist.remove(data)
        previous = current 

    return datalist

datalist = [

    {
        'plate': "01",
        'confidence' : "80"
    },

    {
        'plate': "01",
        'confidence' : "60"
    },

    {
        'plate': "02",
        'confidence' : "91"
    },

    {
        'plate': "02",
        'confidence' : "91"
    },
]


print (filter(datalist))

Ceci est mon code, mais je ne reçois pas le résultat exact.

datalist = [

{
    'plate': "01",
    'confidence' : "80"
},

{
    'plate': "02",
    'confidence' : "91"
},
]

Cela me donne le résultat:

datalist = [

{
    'plate': "01",
    'confidence' : "80"
},

{
    'plate': "01",
    'confidence' : "60"
},

{
    'plate': "02",
    'confidence' : "91"
},

{
    'plate': "02",
    'confidence' : "91"
},
]

qui n'est pas attendu, quel est le problème avec mon code .


2 commentaires

En relation, pas en double exact car ici, nous ne voulons considérer qu'une seule clé lors de l'examen des doublons: Supprimer le dict en double dans la liste en Python


vous pouvez également utiliser pandas import pandas comme pd; df = pd.DataFrame (données = liste de données); df.drop_duplicates (subset = ['plate'], keep = 'first', inplace = True); sortie = df.to_dict (orient = 'enregistrement')


7 Réponses :


6
votes

Si un élément des groupes de doublons est acceptable, vous pouvez faire:

[{'plate': '02', 'confidence': '91'}, {'plate': '01', 'confidence': '80'}]

Sortie

result = list({d['plate']: d for d in reversed(datalist)}.values())

L'idée est de créer un dictionnaire où les clés sont des valeurs de plaque et les valeurs sont les dictionnaires eux-mêmes. Si vous souhaitez conserver les premières entrées en double, utilisez inversé : p>

[{'plate': '02', 'confidence': '91'}, {'plate': '01', 'confidence': '60'}]

Sortie

datalist = [
    {'plate': "01", 'confidence': "80"},
    {'plate': "01", 'confidence': "60"},
    {'plate': "02", 'confidence': "91"},
    {'plate': "02", 'confidence': "91"},
]

result = list({ d['plate'] : d for d in datalist }.values())
print(result)


7 commentaires

Cela produit un résultat erroné car les dernières entrées dupliquées sont conservées, pas la première.


@timgeb OP n'a pas clairement spécifié qu'ils voulaient la première entrée - seulement qu'ils ne voulaient pas d'entrées en double.


@MatthiasFischer OP a spécifié la sortie souhaitée.


vous pouvez toujours le faire en remplaçant datalist par datalist [:: - 1] ou reverse (datalist) pour quelque chose de plus efficace en boucle.


@timgeb Pour le premier exemple, mais nous ne savons pas s'ils veulent toujours la première entrée. Vous avez probablement raison et je suis pédant, mais ce n'est pas explicitement indiqué. :)


@timgeb a mis à jour la réponse!


@DanielMesejo Merci beaucoup pour la réponse rapide. Cela fonctionne comme je le voulais. La seule pièce d'énigme restante était de préserver l'ordre, et pour cela j'ai ajouté une autre ligne de code, results_sorted = sorted (results, key = lambda k: k ['epoch_time']) Heureusement j'ai eu le "Epoch Time" dans la liste, qui et d'autres quelques touches que j'ai supprimées pour la clarté de la question. Et j'ai trié les dictionnaires par "heure d'époque" et ça va maintenant.



3
votes

En supposant que vous ne souhaitiez conserver que le premier dict dupliqué trouvé, vous pouvez utiliser setdefault():

datalist = [
    {"plate": "01", "confidence": "80"},
    {"plate": "01", "confidence": "60"},
    {"plate": "02", "confidence": "91"},
    {"plate": "02", "confidence": "91"},
]

result = {}
for d in datalist:
    result.setdefault(d["plate"], d)

print(list(result.values()))
# [{'plate': '01', 'confidence': '80'}, {'plate': '02', 'confidence': '91'}]

Si vous voulez à la place les derniers doublons, itérer simplement dans reverse () .


0 commentaires


3
votes

Si vous êtes un utilisateur pandas , vous pouvez envisager

>>> pd.DataFrame(datalist).drop_duplicates('plate', keep='last').to_dict(orient='records')
[{'confidence': '60', 'plate': '01'}, {'confidence': '91', 'plate': '02'}]

Si vous souhaitez conserver les derniers doublons vus, passez keep = 'last' .

>>> import pandas as pd
>>> datalist = [{'plate': "01", 'confidence': "80"}, {'plate': "01", 'confidence': "60"}, {'plate': "02", 'confidence': "91"}, {'plate': "02", 'confidence': "91"}]
>>> pd.DataFrame(datalist).drop_duplicates('plate').to_dict(orient='records')                                                                               
[{'confidence': '80', 'plate': '01'}, {'confidence': '91', 'plate': '02'}]


0 commentaires

2
votes

Vous pouvez utiliser un groupe par:

[{'plate': '01', 'confidence': '80'}, {'plate': '02', 'confidence': '91'}]

Résultats:

list(map(lambda x: next(x[1]), groupby(sorted(datalist, key=lambda d: d['plate']), lambda d: d['plate'])))


1 commentaires

cela nécessite le tri de la liste initiale.



3
votes

vous pouvez également utiliser pandas

import pandas as pd
df = pd.DataFrame(data = datalist)
df.drop_duplicates(subset = ['plate'],keep='first',inplace=True)
output = df.to_dict(orient='record')

keep = 'first' ou 'last' vous aidera dans quelle entrée conserver en sortie


3 commentaires

Euh, je ne savais pas que vous pouviez passer 'record' au lieu de 'records' . Cela ne semble pas documenté. +1 pour connaissance obscure :)


Mise à jour: il semble que vous puissiez passer 'r' , 're' , ..., 'records' , 'recordsasdf' , ...


: D Merci @timgeb. Nous pouvons utiliser tout ce qui commence par «r». Je viens de vérifier le code source. github.com/pandas- dev / pandas / blob / v0.23.4 / pandas / core /…



2
votes

Bonne vieille boucle for verbeuse, puis compréhension de la liste:

tmp=[]
for dct in datalist:
  if not any(e[0] == dct["plate"] for e in tmp):
    tmp.append((dct["plate"], dct["confidence"]))


[ {"plate": plate, "confidence": confidence} for plate, confidence in tmp ]
#=> [{'plate': '01', 'confidence': '80'}, {'plate': '02', 'confidence': '91'}]


0 commentaires