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
?
source to share
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])
source to share
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.
source to share