我在Python中有一个dict,它看起来像这样:
{
'key_1': ['3', '2', '4', '4', '5', '6'],
'key_2': ['3', '4', '8', '7', '5', '1'],
'key_3': ['7', '2', '8', '4', '2', '5'],
'key_4': ['3', '2', '4', '4', '5', '6'],
'key_5': ['8', '8', '4', '4', '4', '1'],
'key_6': ['9', '3', '3', '3', '6', '1'],
'key_7': ['4', '2', '3', '6', '4', '5']
}
我需要将其简化为仅包含唯一列表,而不考虑列表中的顺序。例如,以上内容将简化为:
{
'key_1': ['3', '2', '4', '4', '5', '6'],
'key_2': ['3', '4', '8', '7', '5', '1'],
'key_3': ['7', '2', '8', '4', '2', '5'],
'key_5': ['8', '8', '4', '4', '4', '1'],
'key_6': ['9', '3', '3', '3', '6', '1']
}
由于key_1、key_4和key_7在原始dict中都被认为是重复的(key_1和key_4完全相同,key_7与key_1和key_4相同,但顺序不同(。
换句话说,如果任何列表包含相同的数字,无论顺序如何,都应被视为重复。
您可以记录您已经看到的任何序列(排序以确保重复序列的顺序相同(:
mydict = {
'key_1': ['3', '2', '4', '4', '5', '6'],
'key_2': ['3', '4', '8', '7', '5', '1'],
'key_3': ['7', '2', '8', '4', '2', '5'],
'key_4': ['3', '2', '4', '4', '5', '6'],
'key_5': ['8', '8', '4', '4', '4', '1'],
'key_6': ['9', '3', '3', '3', '6', '1'],
'key_7': ['4', '2', '3', '6', '4', '5']
}
result = {}
seen = set()
for k, v in mydict.items():
sorted_v = tuple(sorted(v))
if sorted_v not in seen:
result[k] = v
seen.add(sorted_v)
print(result)
解决方案可以是使用Counter+frozenset:
# this create a dictionary using as keys the list multiset (Counter)
uniques = {frozenset(Counter(values).items()): key for key, values in data.items()}
# reverse the dictionary and build a list from the multiset
result = {key: list(Counter(dict(values)).elements()) for values, key in uniques.items()}
print(result)
输出
{'key_7': ['5', '6', '2', '4', '4', '3'], 'key_2': ['8', '5', '1', '4', '7', '3'], 'key_3': ['5', '8', '2', '2', '4', '7'], 'key_5': ['1', '8', '8', '4', '4', '4'], 'key_6': ['3', '3', '3', '1', '9', '6']}
你可以试试这个:
def reduce_dict(d):
ret = {}
sorts = []
for k, v in d.items():
s = sorted(v)
if s not in sorts:
ret[k] = v
sorts.append(s)
return ret
这将遍历字典,保留所有排序值的列表。
请注意,这只会在python>=3.6中保留。
>>> reduce_dict(d)
{'key_1': ['3', '2', '4', '4', '5', '6'],
'key_2': ['3', '4', '8', '7', '5', '1'],
'key_3': ['7', '2', '8', '4', '2', '5'],
'key_5': ['8', '8', '4', '4', '4', '1'],
'key_6': ['9', '3', '3', '3', '6', '1']}
您还可以尝试利用字典必须具有唯一密钥的事实:
def reduce_dict(d):
rev = {tuple(sorted(v)): (v, k) for k, v in d.items()}
return {k: v for _, (v, k) in rev.items()}
然而,这并不能保证产生第一个双打。请注意,列表必须强制转换为tuples
,因为列表是不可更改的。