Iterate over a tuple by index list

I have a python 3 element tuple that I am trying to sort or reorder using the indices of a 3 element list and I want to know what might be the shortest way to do this.

So far I got:

my_tuple = (10, 20, 30)
new_positions = [2, 0, 1]
my_shuffled_tuple = my_tuple[new_positions[0]], my_tuple[new_positions[1]], my_tuple[new_positions[2]]
# outputs: (30, 10, 20)

      

I also get the same result if:

my_shuffled_tuple = tuple([my_tuple[i] for i in new_positions])

      

Is there a more concise way to create it my_shuffled_tuple

?

+3


source to share


3 answers


One way to do this is with a generator expression as an argument tuple

that accepts an iterable :

In [1]: my_tuple = (10, 20, 30)
   ...: new_positions = [2, 0, 1]
   ...: 

In [2]: my_shuffled_tuple = tuple(my_tuple[i] for i in new_positions)

In [3]: my_shuffled_tuple
Out[3]: (30, 10, 20)

      



If speed is an issue and you are working with a lot of data, you should consider using Numpy. This allows direct indexing with a list or array of indices:

In [4]: import numpy as np

In [5]: my_array = np.array([10, 20, 30])

In [6]: new_positions = [2, 0, 1]  # or new_positions = np.array([2, 0, 1])

In [7]: my_shuffled_array = my_array[new_positions]

In [8]: my_shuffled_array
Out[8]: array([30, 10, 20])

      

+5


source


You can use operator.itemgetter

like this:

from operator import itemgetter

my_tuple = (10, 20, 30)
new_positions = [2, 0, 1]

print itemgetter(*new_positions)(my_tuple)

      

If you will be accessing items my_tuple

(or other things) in a new order, you can keep this one itemgetter

as a helper function:

access_at_2_0_1 = itemgetter(*new_positions)

      



and then it access_at_2_0_1(foo)

will be the same as tuple(foo[2], foo[0], foo[1])

.

This is very useful when you are trying to work with an argsort-like operation (when many arrays need to be re-retrieved in the sort order that comes from sorting another array). Generally by this point, you should probably be using NumPy arrays, but it's still a convenient approach.

Note that because it itemgetter

relies on the __getitem__

(derp) protocol , it is not guaranteed to work with all types of iterations, if that matters.

+3


source


use comprehension in inline function tuple()

(it takes generators)

>>> my_tuple = (10, 20, 30)
>>> new_positions = [2, 0, 1]
>>> tuple(my_tuple[i] for i in new_positions)
(30, 10, 20)

      

+2


source







All Articles