您的问题完全与离散数学中的关系有关,即数组中的所有组合对都具有传递关系,这意味着if a>b and b>c then a>c
. 因此,您可以创建以下列表,因此在长度为 5 的集合中,最小元素应该在其中 4 对中——如果我们有这样数量的对。所以首先我们需要创建这些按第一个元素分组的对,因为我们可以使用模块中的groupby
和chain
函数itertools
:
>>> from itertools import combinations,chain,groupby
>>> from operator import itemgetter
>>> l1= [list(g) for _,g in groupby(sorted(chain.from_iterable(combinations(i,2) for i in [x,y,z])),key=itemgetter(0))]
[[('one', 'four'), ('one', 'four'), ('one', 'three'), ('one', 'two')], [('three', 'five'), ('three', 'four')], [('two', 'five'), ('two', 'four'), ('two', 'three')]]
因此,如果我们有具有 len 4 ,3 ,2, 1 的组,那么我们已经找到了答案,但是如果我们没有找到这样的序列,我们可以反向进行前面的计算以找到我们的元素,如果我们找到一个关系len 4 的组是最大的数字并且...!
>>> l2= [list(g) for _,g in groupby(sorted(chain.from_iterable(combinations(i,2) for i in [x,y,z]),key=itemgetter(1)),key=itemgetter(1))]
[[('two', 'five'), ('three', 'five')], [('one', 'four'), ('two', 'four'), ('one', 'four'), ('three', 'four')], [('two', 'three'), ('one', 'three')], [('one', 'two')]]
所以我们可以做到以下几点:
请注意,我们需要使用set(zip(*i)[1])
来获取我们的特定元素与其相关的元素集,然后用于len
计算这些元素的数量。
>>> [(i[0][0],len(set(zip(*i)[1]))) for i in l1]
[('one', 3), ('three', 2), ('two', 3)]
>>> [(i[0][1],len(set(zip(*i)[0]))) for i in l2]
[('five', 2), ('four', 3), ('three', 2), ('two', 1)]
在第一部分中,我们找到了 4,2,3,所以现在我们只需要找到它可能是的four or five
1。现在我们进入第二部分,我们需要找到一个长度为 3 的序列,4 or 3
所以four
第 4 个元素是因此发现第 5 个元素应该是five
.
编辑:作为一种更优雅、更快捷的方式,您可以使用collections.defaultdict
:
>>> from collections import defaultdict
>>> d=defaultdict(set)
>>> for i,j in chain.from_iterable(combinations(i,2) for i in [x,y,z]) :
... d[i].add(j)
...
>>> d
defaultdict(<type 'set'>, {'three': set(['four', 'five']), 'two': set(['four', 'five', 'three']), 'one': set(['four', 'two', 'three'])})
>>> l1=[(k,len(v)) for k,v in d.items()]
>>> l1
[('three', 2), ('two', 3), ('one', 3)]
>>> d=defaultdict(set)
>>> for i,j in chain.from_iterable(combinations(i,2) for i in [x,y,z]) :
... d[j].add(i) #create dict reversely
...
>>> l2=[(k,len(v)) for k,v in d.items()]
>>> l2
[('four', 3), ('five', 2), ('two', 1), ('three', 2)]