import itertools
A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}}
def key(x):
# List supports ordering
return sorted(list(x[1]))
def gen():
for (group_key, group) in itertools.groupby(sorted(A.items(), key=key), key=key):
gl = list(group)
yield (tuple(x[0] for x in gl),
gl[0][1] # group_key is a list, but we want original set
)
print(dict(gen()))
print(dict((tuple(g[0] for g in group), group_key) for
(group_key, group) in itertools.groupby(sorted(A.items(),
key=lambda x: sorted(list(x[1]))),
key=lambda x: x[1])))
from collections import defaultdict
A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}}
second_new = defaultdict(list)
for a, b in A.items():
second_new[tuple(b)].append(a)
final_dict = {tuple(b):set(a) for a, b in second_new.items()}
>>> A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}}
# First pass: Create a reverse one-to-many mapping.
# The original set() value gets converted to a hashable frozenset()
# and used as a key. The original scalar string key gets accumulated
# in a list to track the multiple occurrences.
>>> reverse = {}
>>> for key, value in A.items():
reverse.setdefault(frozenset(value), []).append(key)
# Second pass: reverse the keys and values. The list of matching
# values gets converted to a hashable tuple (as specified by the OP)
# and the frozenset() gets restored back to the original set() type.
>>> {tuple(value) : set(key) for key, value in reverse.items()}
{('E2', 'E5'): {'5', '7'}, ('E3', 'E8'): {'8', '4'}}
如果您已经准备好让自己相信set->;list->;set conversion是安全的,那么您可以使用一个liner代替generator:
^{pr2}$那么,到底发生了什么?
首先,我们通过调用
.items()
将dict转换为元组的iterable。 我们想将这个iterable的项目组合在一起,这个iterable具有相同的第二个元素(索引为1,或者前一个dict值)。 这正是itertools.groupby
所做的。这些论点是一个重要的和关键的,我们将据此进行分组。看起来,key=lambda kv: kv[1]
是一条路。不幸的是没有。我们可以比较集合的相等性,但是文档说iterable应该被排序。和sorted
函数需要键comparable for order。无法比较集合,因为“排序依据”列表可以。我们可以安全地创建一个包含与set相同元素的列表,但是我们应该对它进行排序(相等的集合可以产生顺序不同的列表,{5, 7} == {7, 5}
,但是[5, 7] != [7, 5]
)。在现在,经过排序和分组,我们得到了以下数据结构:
现在我们可以迭代这个iterable并创建另一个元组的iterable。我们获取每个元组的第二个元素(iterable,索引为1)并将其转换为一个元组(这是我们未来字典的关键)。我们未来词典的价值是源于原始词典的价值。我们可以从元组的第二个元素的某个元素中获取它(这个iterable不能为空,因为}将其转换回list(这是安全的,因为这个列表是从集合中生成的,所以它没有相等的元素,请参见第二个片段)。在
groupby
不能生成空组,请参见第一个片段),或者从{UPD2
在编写解释时,我发现等式键对于
sorted
不合适,但对于groupby
来说很好,因此这里有一个更简单的解决方案,不需要定义key
函数并将list转换回set:你可以试试这个:
输出:
^{pr2}$我将分两次完成转换:
这将给出操作所期望的输出
注意,输入字典没有保证顺序,原始输入中的任何集合也没有。因此,输出不能有一个保证的术语顺序。在
相关问题 更多 >
编程相关推荐