私は次のPython 2.7辞書データ構造を持っています(ソースデータを制御しません-そのまま別のシステムから来ます):
{112762853378: {'dst':['10 .121.4.136 ']、 ' src ':[' 1.2.3.4 ']、 'エイリアス':[' 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、およびaliasは重複できます。すべてのレコードには常にdstとsrcがありますが、3番目のレコードに見られるように、必ずしもすべてのレコードに必ずしもエイリアスがあるわけではありません。
サンプルデータでは、最初の2つのレコードのいずれかが削除されます(どちらのレコードでもかまいません)。 dstとsrcは同じですが、エイリアスが欠落しているため、3番目のレコードは一意と見なされます。
私の目標は、キーに関係なく、dst、src、およびaliasがすべて重複しているすべてのレコードを削除することです。
これはどのようにrookieを達成しますか?
また、Pythonの私の限られた理解は、データ構造を辞書に保存された値を持つ辞書として解釈します... dict of dicts、これは正しいですか?
値が結果辞書にない場合は、辞書の各項目(キーと値のペア)を調べて、結果辞書に追加できます。
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
1つの簡単なアプローチは、各内部辞書の文字列データの連結をキーとして使用して逆辞書を作成することです。したがって、上記のデータを辞書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())
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()(Andrew's Coxの答えのように)と成長するリストを必要とするseenは欠点です。
ただし、1つ目は回避できず(iteritems()を使用しても機能しません)、2つ目はリストを再作成するよりも軽くなりますresult.values()リストの成長結果ループの各ターンに対して。
別の逆辞書のバリエーション:
>>> 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']}}
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]
通信で一意性を見つける方法は、辞書を使用し、目的の一意の値をキーにすることなので、逆の辞書を作成して、値をキーとして構成し、次に「de-中間結果を使用した逆向き辞書。
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)
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]
キーのリストのセットを作成し、それらを繰り返して新しい辞書に入れます:
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]