我是编程的新手,我正在尝试编写一个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都没有搜索我认为会返回任何有用内容的主题。
答案 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 module和Permutation
类:
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.arange
和argsort
来推荐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)