web-dev-qa-db-fra.com

Suppression des doublons du dictionnaire

J'ai la structure de données du dictionnaire Python 2.7 (je ne contrôle pas les données source - provient d'un autre système tel quel):

 {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: ... 
} 

Les clés du dictionnaire seront toujours uniques. Dst, src et alias peuvent être des doublons. Tous les enregistrements auront toujours un dst et un src mais tous les enregistrements n'auront pas nécessairement un alias comme on le voit dans le troisième enregistrement.

Dans l'exemple de données, l'un des deux premiers enregistrements serait supprimé (peu importe pour moi lequel). Le troisième enregistrement serait considéré comme unique car bien que dst et src soient les mêmes, il manque l'alias.

Mon objectif est de supprimer tous les enregistrements où le dst, le src et l'alias ont tous été dupliqués, quelle que soit la clé.

Comment cela recrue accomplit-il cela?

De plus, ma compréhension limitée de Python interprète la structure de données comme un dictionnaire avec les valeurs stockées dans les dictionnaires ... un dict de dict, est-ce correct?

32
Bit Bucket

Vous pouvez parcourir chacun des éléments (la paire clé-valeur) dans le dictionnaire et les ajouter dans un dictionnaire de résultats si la valeur ne figure pas déjà dans le dictionnaire de résultats.

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
40
Andrew Cox

Une approche simple serait de créer un dictionnaire inversé en utilisant la concaténation des données de chaîne dans chaque dictionnaire interne comme clé. Supposons donc que vous ayez les données ci-dessus dans un dictionnaire, 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 vous ne voulez pas une liste de doublons ou quelque chose comme ça, mais que vous voulez juste créer un dict sans doublon, vous pouvez simplement utiliser un dictionnaire ordinaire au lieu d'un defaultdict et l'inverser comme ceci:

>>> 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())
4
senderle
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

résultat

(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']})

Le fait que cette solution crée d'abord une liste input_raw.iteritems () (comme dans la réponse d'Andrew's Cox) et nécessite une liste croissante v sont des inconvénients.
Mais le premier ne peut pas être évité (utiliser iteritems () ne fonctionne pas) et le second est moins lourd que de recréer une liste result.values ​​() à partir de la liste croissante résultat pour chaque tour de boucle.

4
eyquem

Une autre variation de dict inverse:

>>> 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']}}
3
ekhumoro
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]
2
joel3000

Étant donné que le moyen de trouver l'unicité dans les correspondances consiste exactement à utiliser un dictionnaire, la valeur unique souhaitée étant la clé, le chemin à parcourir consiste à créer un dict inversé, où vos valeurs sont composées comme la clé - puis recréer un "dé- inversé "dictionnaire utilisant le résultat intermédiaire.

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)
2
jsbueno
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]
1
reclosedev

Je voudrais simplement faire un ensemble de la liste des clés, puis les répéter dans un nouveau dict:

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']
   }
}

filter = list(set(list(input_raw.keys())))

fixedlist = {}

for i in filter:
    fixedlist[i] = logins[i]
0
Matthew Lee