2015-11-27 39 views
5

Ich habe eine Liste von Diktat, wo ein bestimmter Wert mehrmals wiederholt wird, und ich möchte die doppelten Werte entfernen.Entfernen Sie doppelte JSON-Objekte aus der Liste in Python

Meine Liste:

te = [ 
     { 
     "Name": "Bala", 
     "phone": "None" 
     }, 
     { 
     "Name": "Bala", 
     "phone": "None" 
     }, 
     { 
     "Name": "Bala", 
     "phone": "None" 
     }, 
     { 
     "Name": "Bala", 
     "phone": "None" 
     } 
    ] 

Funktion doppelte Werte entfernen:

def removeduplicate(it): 
    seen = set() 
    for x in it: 
     if x not in seen: 
      yield x 
      seen.add(x) 

Wenn ich diese Funktion aufrufen ich generator object.

<generator object removeduplicate at 0x0170B6E8> 

Wenn ich versuche, über den Generator I TypeError: unhashable type: 'dict'

Gibt es eine Möglichkeit, die doppelte Werte zu entfernen, erhalten iterieren oder über den Generator iterieren

+0

Sie können kein Wörterbuch zu einem Satz hinzufügen, denn Dinge, die zu einem Satz hinzugefügt werden sollen, müssen hashbar sein. – Panda

+1

Als eine Randnotiz: Dies ist keine "Liste von JSON-Objekten", es ist eine Liste von Diktaten. __Es gibt kein JSON-Objekt__ - JSON ist ein Textformat, keine Art von Objekten ... –

Antwort

7

Sie leicht Nachschlüssel durch Wörterbuch Verständnis entfernen da Wörterbuch erlaubt keinen doppelten Schlüssel, wie unten-

te = [ 
     { 
     "Name": "Bala", 
     "phone": "None" 
     }, 
     { 
     "Name": "Bala", 
     "phone": "None" 
     }, 
     { 
     "Name": "Bala", 
     "phone": "None" 
     }, 
     { 
     "Name": "Bala", 
     "phone": "None" 
     }, 
     { 
      "Name": "Bala1", 
      "phone": "None" 
     }  
    ] 

unique = { each['Name'] : each for each in te }.values() 

print unique 

Output-

[{'phone': 'None', 'Name': 'Bala1'}, {'phone': 'None', 'Name': 'Bala'}] 
+0

Wirklich nett, das behalte ich in meiner Tasche.OTOH Bitte beachten Sie, dass dies nicht genau der Funktion des OP entspricht, da er das vollständige Diktat überprüft. In Ihrem Fall werden Sie jedes Diktat mit dem gleichen Namen löschen, wenn es anders ist oder nicht. –

+0

Eigentlich wäre das nach dem Testen eher: 'unique = {repr (each): jeweils für jeden in te} .values ​​()' –

+0

Das OP hat es akzeptiert, aber ich bin mir nicht sicher, ob diese Antwort richtig ist wenn man bedenkt, dass es vorherige Dicts mit späteren Dicts ersetzt (dh von der Liste "te"), dh Daten verliert. Z.B. Wenn 'te' ein anderes Diktat' {'Name': 'Bala', 'phone': '1234'} 'enthielt, wird nur das letzte Element in' te' mit dem Namen 'Bala' beibehalten. – mhawke

2

Da Sie keine dict zu set hinzufügen können. Von this question:

Sie versuchen, ein dict als Schlüssel zu einem anderen dict oder in einem set zu verwenden. Das funktioniert nicht, weil die Schlüssel hashbar sein müssen.

In der Regel sind nur unveränderliche Objekte (Strings, Integer, Floats, Freezens, Tupel von Immutables) hashbar (obwohl Ausnahmen möglich sind).

>>> foo = dict() 
>>> bar = set() 
>>> bar.add(foo) 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
TypeError: unhashable type: 'dict' 
>>> 

Stattdessen sind Sie bereits if x not in seen verwenden, so benutzen Sie einfach eine Liste:

>>> te = [ 
...  { 
...   "Name": "Bala", 
...   "phone": "None" 
...  }, 
...  { 
...   "Name": "Bala", 
...   "phone": "None" 
...  }, 
...  { 
...   "Name": "Bala", 
...   "phone": "None" 
...  }, 
...  { 
...   "Name": "Bala", 
...   "phone": "None" 
...  } 
...  ] 

>>> def removeduplicate(it): 
...  seen = [] 
...  for x in it: 
...   if x not in seen: 
...    yield x 
...    seen.append(x) 

>>> removeduplicate(te) 
<generator object removeduplicate at 0x7f3578c71ca8> 

>>> list(removeduplicate(te)) 
[{'phone': 'None', 'Name': 'Bala'}] 
>>> 
1

Sie können immer noch eine set für Duplikaterkennung verwenden, benötigen Sie nur das Wörterbuch in etwas konvertieren hashbar wie ein tuple. Ihre Wörterbücher können durch tuple(d.items()) in Tupeln umgewandelt werden, wobei d ein Wörterbuch ist. Die Anwendung, das zu Ihrer Generatorfunktion:

def removeduplicate(it): 
    seen = set() 
    for x in it: 
     t = tuple(x.items()) 
     if t not in seen: 
      yield x 
      seen.add(t) 

>>> for d in removeduplicate(te): 
... print(d) 
{'phone': 'None', 'Name': 'Bala'} 

>>> te.append({'Name': 'Bala', 'phone': '1234567890'}) 
>>> te.append({'Name': 'Someone', 'phone': '1234567890'}) 

>>> for d in removeduplicate(te): 
... print(d) 
{'phone': 'None', 'Name': 'Bala'} 
{'phone': '1234567890', 'Name': 'Bala'} 
{'phone': '1234567890', 'Name': 'Someone'} 

Dies ermöglicht eine schnellere Lookup (. Avg O (1)) als ein "gesehen" list (O (n)). Ob sich die zusätzliche Berechnung der Umwandlung jedes Diktats in ein Tupel lohnt, hängt von der Anzahl der Wörterbücher ab, die Sie haben, und davon, wie viele Duplikate vorhanden sind. Wenn es viele Duplikate gibt, wird ein "gesehen" list ziemlich groß werden, und testen, ob ein Diktat bereits gesehen wurde, könnte ein teurer Vorgang werden. Dies könnte die Tupel-Konvertierung rechtfertigen - Sie müssten es testen/profilieren.

Verwandte Themen