Ваша проблема заключается в соотношении в дискретной математике, что все пары комбинаций в ваших массивах имеют переходное отношение вместе это значение 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, так что теперь нам просто нужно найти 1, что его может быть four or five
.now мы идем на вторую часть, что мы должны найти последовательность с длиной 4 or 3
, что four
- 3, так что 4-й элемент найден таким образом, 5-й элемент должен быть five
.
Edit: как более элегантный и быстрый способ вы можете сделать работу с 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)]
Два слово Подсказки: топологические сортировки. – DSM
@NickBailey Я знаю, что это не так. Я более чем доволен намеком на два слова вроде DSM. – lenz