我有一个元素字典:
leveldict = {
(3, 2): (3,), (1, 2, 4): (1, 2), (2, 4, 3): (2, 4), (1, 4): (1,),
(4,): (), (3, 4, 1): (3, 4), (4, 3): (4,), (2, 3, 1): (2, 3),
(2, 4): (2,), (1, 2, 3, 4): (1, 2, 3)
}
我想在leveldict
中找到键值对的所有序列,其中下一个序列项的键是前一个序列项的值。每个元组中项目的顺序不重要。
以下是上面给出的数据的预期输出:
s1 = ((1, 2, 3, 4), (1, 2, 3)), ((2, 3, 1), (2, 3)), ((3, 2), (3,))
s2 = ((1, 2, 4), (1, 2))
s3 = ((2, 4, 3), (2, 4)), ((2, 4), (2,))
s4 = ((3, 4, 1), (3, 4)), ((4, 3), (4,)), ((4,), ())
s5 = ((1, 4), (1,))
注意:leveldict
中的元素可以保证形成这样的序列。
答案 0 :(得分:2)
我们希望忽略每个键元组和值元组中的顺序,因此将它们转换为集合是有意义的。但我们希望将它们用作字典键,因此我们需要使用frozensets,因为普通集不可用。我们可以将它们放入OrderedDict中,以便用最长的密钥更容易地启动每个序列。
from collections import OrderedDict
leveldict = {
(3, 2): (3,), (1, 2, 4): (1, 2), (2, 4, 3): (2, 4), (1, 4): (1,),
(4,): (), (3, 4, 1): (3, 4), (4, 3): (4,), (2, 3, 1): (2, 3),
(2, 4): (2,), (1, 2, 3, 4): (1, 2, 3)
}
# Store in an OrderedDict of frozensets, ordered by length
a = [(frozenset(k), frozenset(v)) for k,v in leveldict.items()]
a.sort(key=lambda t:(len(t[0]), len(t[1])))
odict = OrderedDict(a)
def unfreeze(k, v):
return tuple(k), tuple(v)
all_seqs = []
while odict:
k, v = odict.popitem()
seq = [unfreeze(k, v)]
k = v
while k in odict:
v = odict.pop(k)
seq.append(unfreeze(k, v))
k = v
all_seqs.append(seq)
# Perform a simple numeric sort on the tuple sequences
all_seqs.sort()
for row in all_seqs:
print(row)
<强>输出强>
[((1, 2, 3, 4), (1, 2, 3)), ((1, 2, 3), (2, 3)), ((2, 3), (3,))]
[((1, 2, 4), (1, 2))]
[((1, 3, 4), (3, 4)), ((3, 4), (4,)), ((4,), ())]
[((1, 4), (1,))]
[((2, 3, 4), (2, 4)), ((2, 4), (2,))]
此处的策略是简单地从odict
弹出最长的剩余密钥,并搜索键值链。