根据重复的列表值减少dict,而不考虑列表的顺序

  • 本文关键字:列表 dict 顺序 不考虑 python
  • 更新时间 :
  • 英文 :


我在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_1key_4key_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,因为列表是不可更改的。

最新更新