Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

IIUC, the numpy library has a routine to do this already:

sage: numpy.argsort(L)+1
array([6, 3, 1, 2, 4, 5, 7])

Alternatively, you can use a Schwartzian transform (a.k.a. the "decorate-sort-undecorate" idiom). Start with a list:

sage: L = [2,3,1,6,8,-3,9]

Enumerate it, starting from 1 (the "decorate" part)

sage: list(enumerate(L, 1))
[(1, 2), (2, 3), (3, 1), (4, 6), (5, 8), (6, -3), (7, 9)]

Sort these by the second term, the value:

sage: sorted(enumerate(L, 1), key=lambda x: x[1])
[(6, -3), (3, 1), (1, 2), (2, 3), (4, 6), (5, 8), (7, 9)]

Extract the sorted indices:

sage: ii = [pair[0] for pair in sorted(enumerate(L, 1), key=lambda x: x[1])]
sage: ii
[6, 3, 1, 2, 4, 5, 7]

Finally, we can make this into a proper Permutation:

sage: Permutation(ii)
[6, 3, 1, 2, 4, 5, 7]
sage: Permutation(ii).to_cycles()
[(1, 6, 5, 4, 2, 3), (7,)]

and confirm it by applying it to our list:

sage: P.action(L)
[-3, 1, 2, 3, 6, 8, 9]

IIUC, the numpy library has a routine to do this already:

sage: L = [2,3,1,6,8,-3,9]
sage: numpy.argsort(L)+1
array([6, 3, 1, 2, 4, 5, 7])

Alternatively, you can use a Schwartzian transform (a.k.a. the "decorate-sort-undecorate" idiom). Start with a list:

sage: L = [2,3,1,6,8,-3,9]

Enumerate Starting from our list, we can enumerate it, starting counting from 1 (the "decorate" part)

sage: list(enumerate(L, 1))
[(1, 2), (2, 3), (3, 1), (4, 6), (5, 8), (6, -3), (7, 9)]

Sort these by the second term, the value:

sage: sorted(enumerate(L, 1), key=lambda x: x[1])
[(6, -3), (3, 1), (1, 2), (2, 3), (4, 6), (5, 8), (7, 9)]

Extract the sorted indices:

sage: ii = [pair[0] for pair in sorted(enumerate(L, 1), key=lambda x: x[1])]
sage: ii
[6, 3, 1, 2, 4, 5, 7]

Finally, we can make this into a proper Permutation:

sage: Permutation(ii)
[6, 3, 1, 2, 4, 5, 7]
sage: Permutation(ii).to_cycles()
[(1, 6, 5, 4, 2, 3), (7,)]

and confirm it by applying it to our list:

sage: P.action(L)
[-3, 1, 2, 3, 6, 8, 9]

IIUC, the numpy library has a routine to do this already:

sage: L = [2,3,1,6,8,-3,9]
sage: numpy.argsort(L)+1
array([6, 3, 1, 2, 4, 5, 7])

Alternatively, you can use a Schwartzian transform (a.k.a. the "decorate-sort-undecorate" idiom). Starting from our list, we can enumerate it, counting from 1 (the "decorate" part)

sage: list(enumerate(L, 1))
[(1, 2), (2, 3), (3, 1), (4, 6), (5, 8), (6, -3), (7, 9)]

Sort these by the second term, the value:

sage: sorted(enumerate(L, 1), key=lambda x: x[1])
[(6, -3), (3, 1), (1, 2), (2, 3), (4, 6), (5, 8), (7, 9)]

Extract the sorted indices:

sage: ii = [pair[0] for pair in sorted(enumerate(L, 1), key=lambda x: x[1])]
sage: ii
[6, 3, 1, 2, 4, 5, 7]

Finally, we can make this into a proper Permutation:

sage: Permutation(ii)
[6, 3, 1, 2, 4, 5, 7]
sage: Permutation(ii).to_cycles()
[(1, 6, 5, 4, 2, 3), (7,)]

and confirm it by applying it to our list:

sage: P = Permutation(ii)
sage: P.action(L)
[-3, 1, 2, 3, 6, 8, 9]