我有列表A和B,可以有重复项,例如:
A = ['x', 'x', 7]
B = [7, 'x', 'x']
现在我想要所有将列表B置于列表A中的索引排列:
[1, 2, 0] # because [B[1], B[2], B[0]] == A
[2, 1, 0] # because [B[2], B[1], B[0]] == A
有没有办法实现这一点而不会迭代所有可能的排列? 我已经使用
了import itertools
for p in itertools.permutations(range(len(B))):
if A == permute(B,p):
迭代所有可能的排列并检查我想要的排列,但我想更快地找到合适的排列。
答案 0 :(得分:2)
您应该将问题分解为两个:
sigma_0
映射到B
的特定排列A
S_B
然后你正在照看的那只是{sigma_0 \circ \sigma, sigma \in S_B}
。
现在问题变成了:我们如何确定S_B
?要做到这一点,您可以观察到,如果您将{0,1,2,..,n}
集(在您的情况下为n=2
)写为A_1 \cup .. A_k
,其中每个A_i
对应于{中的索引{1}}对应于第i个元素(在您的情况下,您将拥有B
和A_1 = {1,2}
),然后A_2 = {0}
的每个元素都可以以独特的方式写入产品S_B
,其中每个tau_1 \circ .. tau_k
都是tau_i
上的排列。
因此,在您的案例A_i
中,您可以S_B = {id, (1,2)}
。因此,你所追求的集合是sigma_0 = (0,2)
。
答案 1 :(得分:1)
这是一种方法。我的perms
函数会生成所有有效的排列。首先,我收集B中每个元素的索引,然后通过总是为A中的每个项目选择一个仍然可用的索引来递归地构建和产生排列,直到准备好换取排列。
from collections import defaultdict
def perms(A, B):
indexes = defaultdict(set)
for i, e in enumerate(B):
indexes[e].add(i)
def find(perm):
k = len(perm)
if k == len(A):
yield perm
return
I = indexes[A[k]]
for i in list(I):
I.remove(i)
yield from find(perm + (i,))
I.add(i)
yield from find(())
用法:
A = ['x', 'x', 7]
B = [7, 'x', 'x']
for perm in perms(A, B):
print(perm)
输出:
(1, 2, 0)
(2, 1, 0)
答案 2 :(得分:0)
你可以分三步完成。首先,从列表B创建一个字典,其中项目为键,索引为值。在您的情况下,列表B的字典:
B = [7, 'x', 'x']
7 - [0]
'x' - [1, 2]
然后,浏览列表A并构建一个索引,将List A索引映射到相应的List B索引。那就是:
A = ['x', 'x', 7]
0 - [1, 2]
1 - [1, 2]
2 - [0]
由此,您可以生成所有有效映射。编写代码应该很容易,给定上面的索引,将生成[1, 2, 0]
和[2, 1, 0]
。
答案 3 :(得分:0)
这是Python中的一些东西。我使用字符串进行散列,因为我不熟悉如何在Python中将集合和数组作为递归参数传递,尽管它们可能更有效。
A = ['x', 'x', 7, 'y', 8, 8]
B = [7, 'x', 8, 'x', 8, 'y']
H = {}
# record the indexes of elements in B
for i in xrange(0,len(B)):
if B[i] in H:
H[ B[i] ].append(str(i))
else:
H[ B[i] ] = [str(i)]
# build permutations in the order that the elements are encountered in A
def perms(perm,i,visited,l):
if i==l:
print perm
return
for j in H[ A[i] ]:
if j not in visited:
perms(perm + j,i + 1,visited + j,l)
perms("",0,"",len(A))
输出:
130524
130542
310524
310542