我有相邻的配对(1:2)(2:3)(3:4)(4:5)(7:8).. ..
我想识别所有的排列,但是这一对的每一面只能在一个排列中使用一次,我想知道未使用的值。
即
(1:2)(3:4)(7:8)未使用:5
(2:3)(4:5)(7:8)未使用:1
(1:2)(4:5)(7:8)未使用:3
提前感谢您的建议和想法。
我正在使用的一些实际配对列表是
list1 = [(427,3434),(614,2445),(840,614),(910,3939),(1065,4314),(1347,2616),(2445,427),(2616) ,3901),(2749,1065),(3403,910),(3434,1347),(3659,1411),(3901,3684),(3939,2638),(4203,3403),(4314,840) )]
list2 = [(1218,134),(3344,1218),(3683,3344),(2055,3683),(2709,2055)]
答案 0 :(得分:0)
这是一个快速的程序,我一起解决这个问题。这可能不是最有效的方法,但它完成了工作。
l = [(1,2),(2,3),(3,4),(4,5)] # replace with whatever your full list is
import itertools
for perm in itertools.permutations(l,len(l) / 2):
pair_list = []
for pair in perm:
if pair[0] in itertools.chain(*(i for i in pair_list)) \
or pair[1] in itertools.chain(*(i for i in pair_list)):
break
pair_list.append(pair)
if len(pair_list) == len(l) / 2:
unused = []
for n in itertools.chain(*(i for i in l)):
if n not in itertools.chain(*(i for i in pair_list)) and n not in unused:
unused.append(n)
print pair_list,'unused:',unused
此外,您确定要确定所有排列吗?为了获得准确的输出,我需要将itertools.permutations
替换为itertools.combinations
。
以下是我使用itertools.permutations
获得的输出:
[(1, 2), (3, 4)] unused: [5]
[(1, 2), (4, 5)] unused: [3]
[(2, 3), (4, 5)] unused: [1]
[(3, 4), (1, 2)] unused: [5]
[(4, 5), (1, 2)] unused: [3]
[(4, 5), (2, 3)] unused: [1]
然而我使用itertools.combinations
:
[(1, 2), (3, 4)] unused: [5]
[(1, 2), (4, 5)] unused: [3]
[(2, 3), (4, 5)] unused: [1]
编辑:好的,这个新修订版有点困难。我现在所做的是找到较大列表中所有子组彼此相邻的子组。我找到每个子组的组合,然后将它们全部放回到最后一个itertools.product
。另外,在我的测试用例中,我在最后添加了一对(8,9)以确保一切适用于多个组。这是代码:
l = [(1,2),(2,3),(3,4),(4,5),(7,8),(8,9)]
import itertools,math
## Create sublists for each set of adjacent pairs
l.sort(lambda x,y:cmp(x[0],y[0]))
newl = []
subl = []
for i in range(len(l)):
if subl == []:
subl.append(l[i])
else:
if l[i][0] == subl[-1][1]:
subl.append(l[i])
else:
newl.append(subl)
subl = [l[i]]
newl.append(subl)
pair_lists = []
## Find all combinations for each sublist
for subl in newl:
cur_pair_list = []
for perm in itertools.combinations(subl,int(math.ceil(len(subl) / 2.0))):
pair_list = []
for pair in perm:
if pair[0] in itertools.chain(*pair_list) \
or pair[1] in itertools.chain(*pair_list):
break
pair_list.append(pair)
if len(pair_list) == int(math.ceil(len(subl) / 2.0)):
cur_pair_list.append(pair_list)
pair_lists.append(cur_pair_list)
## Combine combinations for each sublist and determine unused for each combination
final_list = list(list(itertools.chain(*i)) for i in itertools.product(*pair_lists))
for subl in final_list:
unused = []
for n in itertools.chain(*l):
if n not in itertools.chain(*subl) and n not in unused:
unused.append(n)
print subl,'unused:',unused
这是输出:
[(1, 2), (3, 4), (7, 8)] unused: [5, 9]
[(1, 2), (3, 4), (8, 9)] unused: [5, 7]
[(1, 2), (4, 5), (7, 8)] unused: [3, 9]
[(1, 2), (4, 5), (8, 9)] unused: [3, 7]
[(2, 3), (4, 5), (7, 8)] unused: [1, 9]
[(2, 3), (4, 5), (8, 9)] unused: [1, 7]
编辑#2:
所以在这里,我只需要做的新事就是改变列表的排序方式。评论## Find all combinations for each sublist
下面的所有代码都可以保持不变。
以下是该评论的新代码:
l = [(427, 3434), (614, 2445), (840, 614), (910, 3939), (1065, 4314), (1347, 2616), (2445, 427), (2616, 3901), (2749, 1065), (3403, 910), (3434, 1347), (3659, 1411), (3901, 3684), (3939, 2638), (4203, 3403), (4314, 840)]
import itertools,math
def sort(l):
l = list(l)
newl = []
subl = []
i = l[0]
while len(l) > 0:
subl.append(i)
l.remove(i)
k = None
for j in l:
if j[0] == i[1]:
k = j
break
if k:
i = k
else:
newl.append(subl)
subl = []
if len(l) > 0:
i = l[0]
i = 0
while i < len(newl):
j = 0
while j < len(newl):
if newl[j][-1][1] == newl[i][0][0]:
for k in newl[j][::-1]:
newl[i].insert(0,k)
newl.pop(j)
continue
j += 1
i += 1
return newl
pair_lists = []
newl = sort(l)
这是我在新列表中运行时得到的输出:
[(2749, 1065), (4314, 840), (614, 2445), (427, 3434), (1347, 2616), (3901, 3684), (4203, 3403), (910, 3939), (3659, 1411)] unused: [2638]
[(2749, 1065), (4314, 840), (614, 2445), (427, 3434), (1347, 2616), (3901, 3684), (4203, 3403), (3939, 2638), (3659, 1411)] unused: [910]
[(2749, 1065), (4314, 840), (614, 2445), (427, 3434), (1347, 2616), (3901, 3684), (3403, 910), (3939, 2638), (3659, 1411)] unused: [4203]