从字典中移除重复项
我有一个这样的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和alias可以有重复的值。所有记录都会有dst和src,但并不是每条记录都有alias,就像第三条记录那样。
在这个示例数据中,前两条记录中的任意一条都可以被删除(我对删除哪一条都无所谓)。第三条记录被认为是独特的,因为虽然dst和src是相同的,但它缺少alias。
我的目标是删除所有dst、src和alias都重复的记录,不管它们的键是什么。
这个新手该怎么做呢?
另外,我对Python的理解有限,我认为这个数据结构是一个字典,里面的值也是字典……也就是字典中的字典,这样理解对吗?
11 个回答
4
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 Cox的回答中提到的),并且需要一个不断增长的列表 seen。
不过,第一个问题是无法避免的(使用iteritems()是行不通的),而第二个问题比在每次循环中重新创建一个列表 result.values() 要轻便一些。
6
一种简单的方法是创建一个反向字典,使用每个内部字典中字符串数据的拼接作为键。假设你有上面的数据在一个字典中,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())
53
你可以逐个查看字典里的每一项(键值对),如果这个值还没有在结果字典里,就把它添加进去。
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