2012-01-05 20 views
17

que tener la estructura siguiente Python 2.7 diccionario de datos (no controlo de datos de origen - viene de otro sistema tal cual):la eliminación de duplicados del diccionario

 
{112762853378: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'], 
    'alias': ['www.example.com'] 
    }, 
112762853385: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'], 
    'alias': ['www.example.com'] 
    }, 
112760496444: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'] 
    }, 
112760496502: 
    {'dst': ['10.122.195.34'], 
    'src': ['4.3.2.1'] 
    }, 
112765083670: ... 
} 

Las claves de un diccionario siempre será única. Dst, src y alias pueden ser duplicados. Todos los registros siempre tendrán un dst y src pero no todos los registros necesariamente tendrán un alias como se ve en el tercer registro.

En la muestra de datos se eliminarán los dos primeros registros (no me importa cuál). El tercer registro se consideraría único, ya que aunque dst y src son lo mismo, falta alias.

Mi objetivo es eliminar todos los registros donde dst, src y alias han sido duplicados, independientemente de la clave.

¿Cómo funciona esto rookie lograr esto?

Además, mi comprensión limitada de Python interpreta la estructura de datos como un diccionario con los valores almacenados en los diccionarios ... un dict de dicts, ¿es correcto?

Respuesta

26

Usted podría ir bien cada uno de los elementos (el valor par de claves) en el diccionario y agregarlos en un diccionario resultado si el valor era no ya en el diccionario de resultados.

input_raw = {112762853378: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'], 
    'alias': ['www.example.com'] 
    }, 
112762853385: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'], 
    'alias': ['www.example.com'] 
    }, 
112760496444: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'] 
    }, 
112760496502: 
    {'dst': ['10.122.195.34'], 
    'src': ['4.3.2.1'] 
    } 
} 

result = {} 

for key,value in input_raw.items(): 
    if value not in result.values(): 
     result[key] = value 

print result 
+4

Este es un buen punto de partida, pero me siento obligado a señalar que será lento para grandes colecciones de datos, porque con cada ciclo, crea una nueva lista de valores y realiza una búsqueda lineal sobre ella. – senderle

+0

Esto funcionó con simplicidad y belleza. –

+0

@senderle: Agradezco su pensamiento y comentario con respecto a la velocidad y tomará en cuenta si es necesario. ¿Te importa ampliar esta respuesta para aumentar el rendimiento? –

2

Un enfoque simple sería crear un diccionario inverso utilizando la concatenación de los datos de cadena en cada diccionario interno como una clave. Así que supongamos que tiene los datos anteriores en un diccionario, d:

>>> import collections 
>>> reverse_d = collections.defaultdict(list) 
>>> for key, inner_d in d.iteritems(): 
...  key_str = ''.join(inner_d[k][0] for k in ['dst', 'src', 'alias'] if k in inner_d) 
...  reverse_d[key_str].append(key) 
... 
>>> duplicates = [keys for key_str, keys in reverse_d.iteritems() if len(keys) > 1] 
>>> duplicates 
[[112762853385, 112762853378]] 

Si no desea una lista de duplicados o algo por el estilo, pero sólo desea crear un duplicado dict-menos, usted podría utilizar un diccionario normal en lugar de defaultdict y volver a invertirlo de este modo:

>>> for key, inner_d in d.iteritems(): 
...  key_str = ''.join(inner_d[k][0] for k in ['dst', 'src', 'alias'] if k in inner_d) 
...  reverse_d[key_str] = key 
>>> new_d = dict((val, d[val]) for val in reverse_d.itervalues()) 
+0

¡Tan complicado! – eyquem

1

Desde el camino para encontrar la singularidad de correspondencias es exactamente usar un diccionario, con el valor único deseada es la clave, el camino a seguir es el de crear un diccionario invertido, donde sus valores se componen como la clave - luego recree un diccionario "revertido" usando el resultado intermedio.

dct = {112762853378: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'], 
    'alias': ['www.example.com'] 
    }, 
112762853385: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'], 
    'alias': ['www.example.com'] 
    }, 
112760496444: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'] 
    }, 
112760496502: 
    {'dst': ['10.122.195.34'], 
    'src': ['4.3.2.1'] 
    }, 
    } 

def remove_dups (dct): 
    reversed_dct = {} 
    for key, val in dct.items(): 
     new_key = tuple(val["dst"]) + tuple(val["src"]) + (tuple(val["alias"]) if "alias" in val else (None,)) 
     reversed_dct[new_key] = key 
    result_dct = {} 
    for key, val in reversed_dct.items(): 
     result_dct[val] = dct[val] 
    return result_dct 

result = remove_dups(dct) 
+0

Tanto complicado – eyquem

0
from collections import defaultdict 

dups = defaultdict(lambda : defaultdict(list)) 

for key, entry in data.iteritems(): 
    dups[tuple(entry.keys())][tuple([v[0] for v in entry.values()])].append(key) 

for dup_indexes in dups.values(): 
    for keys in dup_indexes.values(): 
     for key in keys[1:]: 
      if key in data: 
       del data[key] 
+0

Sobrecomplicado – eyquem

1
dups={} 

for key,val in dct.iteritems(): 
    if val.get('alias') != None: 
     ref = "%s%s%s" % (val['dst'] , val['src'] ,val['alias'])# a simple hash 
     dups.setdefault(ref,[]) 
     dups[ref].append(key) 

for k,v in dups.iteritems(): 
    if len(v) > 1: 
     for key in v: 
      del dct[key] 
+0

Tuve que actualizar esto. Debería funcionar ahora, si entiendo la pregunta correctamente. – joel3000

2

Otra variación dict inversa:

>>> import pprint 
>>> 
>>> data = { 
... 112762853378: 
... {'dst': ['10.121.4.136'], 
...  'src': ['1.2.3.4'], 
...  'alias': ['www.example.com'] 
... }, 
... 112762853385: 
... {'dst': ['10.121.4.136'], 
...  'src': ['1.2.3.4'], 
...  'alias': ['www.example.com'] 
... }, 
... 112760496444: 
... {'dst': ['10.121.4.136'], 
...  'src': ['1.2.3.4'] 
... }, 
... 112760496502: 
... {'dst': ['10.122.195.34'], 
...  'src': ['4.3.2.1'] 
... }, 
... } 
>>> 
>>> keep = set({repr(sorted(value.items())):key 
...    for key,value in data.iteritems()}.values()) 
>>> 
>>> for key in data.keys(): 
...  if key not in keep: 
...   del data[key] 
... 
>>> 
>>> pprint.pprint(data) 
{112760496444L: {'dst': ['10.121.4.136'], 'src': ['1.2.3.4']}, 
112760496502L: {'dst': ['10.122.195.34'], 'src': ['4.3.2.1']}, 
112762853378L: {'alias': ['www.example.com'], 
       'dst': ['10.121.4.136'], 
       'src': ['1.2.3.4']}} 
+0

Fino pero complicado en mi opinión – eyquem

+0

Parece que esto contaría '{'src': ['1.2.3.4'], 'dst': ['10.121.3.1236']}' y '{'src': ['10.121 .3.1236 '],' dst ': [' 1.2.3.4 ']} 'como duplicados entre sí ... – senderle

+0

@senderle. ¡Bien descrito! Corregido eso ahora, FWIW. También debería señalar que esta solución, aunque compacta, es bastante ineficiente en comparación con algunas de las otras. – ekhumoro

2
input_raw = {112762853378: {'dst': ['10.121.4.136'], 
          'src': ['1.2.3.4'], 
          'alias': ['www.example.com'] }, 
      112762853385: {'dst': ['10.121.4.136'], 
          'src': ['1.2.3.4'], 
          'alias': ['www.example.com'] }, 
      112760496444: {'dst': ['10.121.4.299'], 
          'src': ['1.2.3.4'] }, 
      112760496502: {'dst': ['10.122.195.34'], 
          'src': ['4.3.2.1'] }, 
      112758601487: {'src': ['1.2.3.4'], 
          'alias': ['www.example.com'], 
          'dst': ['10.121.4.136']}, 
      112757412898: {'dst': ['10.122.195.34'], 
          'src': ['4.3.2.1'] }, 
      112757354733: {'dst': ['124.12.13.14'], 
          'src': ['8.5.6.0']},    
      } 

for x in input_raw.iteritems(): 
    print x 
print '\n---------------------------\n' 

seen = [] 

for k,val in input_raw.items(): 
    if val in seen: 
     del input_raw[k] 
    else: 
     seen.append(val) 


for x in input_raw.iteritems(): 
    print x 

resultado

(112762853385L, {'src': ['1.2.3.4'], 'dst': ['10.121.4.136'], 'alias': ['www.example.com']}) 
(112757354733L, {'src': ['8.5.6.0'], 'dst': ['124.12.13.14']}) 
(112758601487L, {'src': ['1.2.3.4'], 'dst': ['10.121.4.136'], 'alias': ['www.example.com']}) 
(112757412898L, {'src': ['4.3.2.1'], 'dst': ['10.122.195.34']}) 
(112760496502L, {'src': ['4.3.2.1'], 'dst': ['10.122.195.34']}) 
(112760496444L, {'src': ['1.2.3.4'], 'dst': ['10.121.4.299']}) 
(112762853378L, {'src': ['1.2.3.4'], 'dst': ['10.121.4.136'], 'alias': ['www.example.com']}) 

--------------------------- 

(112762853385L, {'src': ['1.2.3.4'], 'dst': ['10.121.4.136'], 'alias': ['www.example.com']}) 
(112757354733L, {'src': ['8.5.6.0'], 'dst': ['124.12.13.14']}) 
(112757412898L, {'src': ['4.3.2.1'], 'dst': ['10.122.195.34']}) 
(112760496444L, {'src': ['1.2.3.4'], 'dst': ['10.121.4.299']}) 

El hecho de que esta solución crea tes primero una lista input_raw.iteritems() (como en la respuesta de Andrew's Cox) y requiere una lista creciente visto son inconvenientes.
Pero el primero no se puede evitar (usar iteritems() no funciona) y el segundo es menos pesado que volver a crear una lista result.values ​​() de la lista de crecimiento resultado para cada vuelta de lazo.

-2
example = { 
    'id1': {'name': 'jay','age':22,}, 
    'id2': {'name': 'salman','age': 52,}, 
    'id3': {'name':'Ranveer','age' :26,}, 
    'id4': {'name': 'jay', 'age': 22,}, 
} 
for item in example: 
    for value in example: 
     if example[item] ==example[value]: 
      if item != value: 
       key = value 
       del example[key] 
print "example",example   
+0

Por favor, formatee su respuesta con el botón '{}', el formato importa en Python. Y es una muy mala idea modificar listas o diccionarios, mientras se itera sobre ellos. Muy mal. – MrT

+0

Bienvenido a StackOverflow: si publica código, XML o muestras de datos, resalte esas líneas en el editor de texto y haga clic en el botón "muestras de código" ({}) en la barra de herramientas del editor o use Ctrl + K en su teclado formato y sintaxis resaltarlo! – WhatsThePoint

Cuestiones relacionadas