在Python中反转排列

时间:2012-02-07 23:39:33

标签: python permutation

我是编程的新手,我正在尝试编写一个Python函数,使用以下代码在{1,2,3,...,n}上找到排列的倒数:

def inv(str):
    result = []
    i = list(str).index(min(list(str)))
    while min(list(str)) < len(list(str)) + 1:
        list(str)[i : i + 1] = [len(list(str)) + 1]
        result.append(i + 1)
    return result

但是,当我尝试使用该功能时,inv('<mypermutation>')会返回[]。我错过了什么吗? Python是否因为某些语法原因跳过了我的while循环而我不明白?我的google和stackoverflow都没有搜索我认为会返回任何有用内容的主题。

7 个答案:

答案 0 :(得分:6)

如果您只想要反向排列,可以使用

def inv(perm):
    inverse = [0] * len(perm)
    for i, p in enumerate(perm):
        inverse[p] = i
    return inverse

perm = [3, 0, 2, 1]
print(inv(perm))
for i in perm:
    print(inv(perm)[i])

[1, 3, 2, 0]
0
1
2
3

答案 1 :(得分:1)

如果我有这个错误,请纠正我,但我认为当我将str更改为列表时,我的代码会出现问题:str是一个字符串,而list(str)是一个列表字符串元素。但是,由于字符串元素无法在数字上与数字进行比较,因此代码无法生成结果([]除外)。

答案 2 :(得分:1)

A&#34;功能风格&#34;版本:

def invert_permutation(permutation):
    return [i for i, j in sorted(enumerate(permutation), key=lambda (_, j): j)]

基本上,在排列中用它们的值 j 对排列的索引 i 进行排序会产生所需的逆。

p = [2, 1, 5, 0, 4, 3]

invert_permutation(p)
# [3, 1, 0, 5, 4, 2]

# inverse of inverse = identity
invert_permutation(invert_permutation(p)) == p
# True

答案 3 :(得分:1)

也许有一条最短的路:

def invert(p):
    return [p.index(l) for l in range(len(p))] 

这样:

perm = [3, 0, 2, 1]; print(invert(perm))

返回

  

[1,3,2,0]

答案 4 :(得分:1)

自从这里没有人推荐它以来,我认为应该提到SymPy具有entire combinatorics modulePermutation类:

from sympy.combinatorics import Permutation
o = [3, 0, 2, 1]
p = Permutation(o)
inv = p.__invert__()
print(inv.array_form) # [1, 3, 2, 0]

使用SymPy类可让您访问许多其他有用的方法,例如使用==比较等效排列。

您可以阅读sympy.combinatorics.Permutation源代码here

除此之外,我会在页面上使用np.arangeargsort来推荐the answer

答案 5 :(得分:1)

我相信反转排列perm的最佳方法是

pinv = sorted(range(len(perm)), key=perm.__getitem__)

这避免了反复调用.index()(如SeF的回答),这可能不是很有效(二次时间复杂度,而排序只需要O(n log n))。

但是请注意,无论输入是否是{0,1,...,n-1的排列,这都会产生{0,1,... n-1}的排列。 }或{1,2,...,n}中的一个(后者是问题中指出的内容)。如果假设输出是{1,2,...,n}的排列,则结果的每个元素都必须增加一个,例如:

pinv = [i+1 for i in sorted(range(len(perm)), key=perm.__getitem__)]

答案 6 :(得分:0)

其他答案是正确的,但就其价值而言,使用numpy的性能更高:

inverse_perm = np.arange(len(permutation))[np.argsort(permutation)]

计时代码:

def invert_permutation_list_scan(p):
    return [p.index(l) for l in range(len(p))]

def invert_permutation_list_comp(permutation):
    return [i for i, j in sorted(enumerate(permutation), key=lambda i_j: i_j[1])]

def invert_permutation_numpy(permutation):
    return np.arange(len(permutation))[np.argsort(permutation)] 

x = np.random.randn(10000)
perm = np.argsort(x)
permlist = list(perm)
assert np.array_equal(invert_permutation_list_scan(permlist), invert_permutation_numpy(perm))
assert np.array_equal(invert_permutation_list_comp(perm), invert_permutation_numpy(perm))
%timeit invert_permutation_list_scan(permlist)
%timeit invert_permutation_list_comp(perm)
%timeit invert_permutation_numpy(perm)

结果:

7.16 s ± 109 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
6.18 ms ± 45.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
524 µs ± 8.93 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)