Удаление дубликатов из словаря
У меня есть следующая структура данных словаря Python 2.7 (я не контролирую исходные данные - поступает из другой системы как есть):
{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: ...
}
Клавиши словаря всегда будут уникальными. Dst, src и псевдоним могут быть дублирующими. Все записи всегда будут иметь dst и src, но не каждая запись обязательно будет иметь псевдоним, как показано в третьей записи.
В образце данных будет удалена одна из первых двух записей (для меня это не имеет значения). Третья запись будет считаться уникальной, поскольку, хотя dst и src являются одинаковыми, отсутствует псевдоним.
Моя цель - удалить все записи, в которых все dst, src и alias были дублированы - независимо от ключа.
Как этот новичок справляется с этим?
Кроме того, мое ограниченное понимание Python интерпретирует структуру данных как словарь со значениями, хранящимися в словарях... dict dicts, это правильно?
Ответы
Ответ 1
Вы можете пройти через каждый из элементов (пара значений ключа) в словаре и добавить их в словарь результатов, если это значение еще не было в словаре результатов.
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
Ответ 2
Одним простым подходом было бы создание обратного словаря, использующего конкатенацию строковых данных в каждом внутреннем словаре в качестве ключа. Итак, скажите, что у вас есть вышеуказанные данные в словаре, 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]]
Если вам не нужен список дубликатов или что-то в этом роде, но просто нужно создать дубликат без ограничений, вы можете просто использовать обычный словарь вместо defaultdict
и перевернуть его так:
>>> 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())
Ответ 3
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
результат
(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']})
Факты, что это решение создает сначала список input_raw.iteritems() (как в ответе Эндрю Кокса), и требует, чтобы растущий список видел - недостатки.
Но нельзя избежать первого (использование iteritems() не работает), а второе менее тяжелое, чем повторное создание списка result.values () из растущего списка result для каждого поворота цикла.
Ответ 4
Другая вариация в обратном типе:
>>> 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']}}
Ответ 5
Так как способ найти уникальность в соответствиях - это именно то, что нужно использовать словарь, с желаемым уникальным значением, являющимся ключом, способ сделать это - создать обратный dict, где ваши значения составлены как ключ, а затем воссоздать "отмененный" словарь с использованием промежуточного результата.
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)
Ответ 6
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]
Ответ 7
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]
Ответ 8
Я бы просто сделал набор из списка ключей, затем перебрал бы их в новый 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]
Ответ 9
Ты можешь использовать
set(dictionary)
чтобы решить вашу проблему.
Ответ 10
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