[英]How to get all orderings of a list such that the list is equal to another list?
I have lists A and B, which can have duplicates, for example: 我有列表A和B,可以有重复项,例如:
A = ['x', 'x', 7]
B = [7, 'x', 'x']
Now I want all index permutations that permute list B into list A: 现在我想要所有将列表B置于列表A中的索引排列:
[1, 2, 0] # because [B[1], B[2], B[0]] == A
[2, 1, 0] # because [B[2], B[1], B[0]] == A
Is there are way to achieve this without iterating over all possible permutations? 有没有办法实现这一点,而不是迭代所有可能的排列? I already use
我已经用过
import itertools
for p in itertools.permutations(range(len(B))):
if A == permute(B,p):
to iterate over all possible permutations and check for the ones I want, but I want to have the right ones faster. 迭代所有可能的排列并检查我想要的排列,但我希望更快地拥有正确的排列。
You should decompose your problem in two : 您应该将问题分解为两个:
sigma_0
that maps B
onto A
B
映射到A
的特定排列sigma_0
S_B
of all the permutations that map B onto itself S_B
Then the set you are looking after is just {sigma_0 \\circ \\sigma, sigma \\in S_B}
. 然后你正在寻找的集合只是
{sigma_0 \\circ \\sigma, sigma \\in S_B}
。
Now the question becomes : how to we determine S_B
? 现在问题变成:如何确定
S_B
? To do this, you can just observe that if you write the set {0,1,2,..,n}
(with n=2
in your case) as A_1 \\cup .. A_k
, where each A_i
corresponds to the indices in B
that correspond to the i-th element (in your case, you would have A_1 = {1,2}
and A_2 = {0}
), then each element of S_B
can be written in a unique manner as a product tau_1 \\circ .. tau_k
where each tau_i
is a permutation that acts on A_i
. 要做到这一点,您可以观察到如果您将集合
{0,1,2,..,n}
(在您的情况下为n=2
)写为A_1 \\cup .. A_k
,其中每个A_i
对应于索引在B
中对应于第i个元素(在您的情况下,您将有A_1 = {1,2}
且A_2 = {0}
),那么S_B
每个元素都可以以独特的方式写为产品tau_1 \\circ .. tau_k
其中每个tau_i
是一个作用于A_i
的排列。
So, in your case S_B = {id, (1,2)}
and you can take sigma_0 = (0,2)
. 因此,在您的情况下,
S_B = {id, (1,2)}
,您可以使用sigma_0 = (0,2)
。 It follows that the set your are after is {(0,2), (2,0,1)}
. 因此,你所追求的集合是
{(0,2), (2,0,1)}
。
Here's one way to do it. 这是一种方法。 My
perms
function generates all valid permutations. 我的
perms
函数生成所有有效的排列。 First I collect the indexes for each element in B, then I recursively build and yield the permutations by always picking one of the still available indexes for each item in A until a permutation is ready to be yielded. 首先,我收集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(())
Usage: 用法:
A = ['x', 'x', 7]
B = [7, 'x', 'x']
for perm in perms(A, B):
print(perm)
Output: 输出:
(1, 2, 0)
(2, 1, 0)
You could do this in three steps. 你可以分三步完成。 First, create a dictionary from list B that has items as keys and indexes as values.
首先,从列表B创建一个字典,其中项目为键,索引为值。 In your case, the dictionary for your list B:
在您的情况下,列表B的字典:
B = [7, 'x', 'x']
7 - [0]
'x' - [1, 2]
Then, go through your list A and build an index that maps List A indexes to their corresponding List B indexes. 然后,浏览列表A并构建一个索引,将List A索引映射到相应的List B索引。 That is:
那是:
A = ['x', 'x', 7]
0 - [1, 2]
1 - [1, 2]
2 - [0]
From that, you can generate all of the valid mappings. 从那里,您可以生成所有有效的映射。 It should be easy enough to write code that, given the index above, will generate
[1, 2, 0]
and [2, 1, 0]
. 应该很容易编写代码,给定上面的索引,将生成
[1, 2, 0]
和[2, 1, 0]
。
Here's something in Python. 这是Python中的一些东西。 I used strings for hashing since I'm not familiar with how to pass sets and arrays as recursive arguments in Python, although they might be more efficient.
我使用字符串进行散列,因为我不熟悉如何在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))
Output: 输出:
130524
130542
310524
310542
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.