Python: filtering lists by indices

PythonListFilterIndexing

Python Problem Overview


In Python I have a list of elements aList and a list of indices myIndices. Is there any way I can retrieve all at once those items in aList having as indices the values in myIndices?

Example:

>>> aList = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> myIndices = [0, 3, 4]
>>> aList.A_FUNCTION(myIndices)
['a', 'd', 'e']

Python Solutions


Solution 1 - Python

I don't know any method to do it. But you could use a list comprehension:

>>> [aList[i] for i in myIndices]

Solution 2 - Python

Definitely use a list comprehension but here is a function that does it (there are no methods of list that do this). This is however bad use of itemgetter but just for the sake of knowledge I have posted this.

>>> from operator import itemgetter
>>> a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> my_indices = [0, 3, 4]
>>> itemgetter(*my_indices)(a_list)
('a', 'd', 'e')

Solution 3 - Python

Indexing by lists can be done in numpy. Convert your base list to a numpy array and then apply another list as an index:

>>> from numpy import array
>>> array(aList)[myIndices]
array(['a', 'd', 'e'], 
  dtype='|S1')

If you need, convert back to a list at the end:

>>> from numpy import array
>>> a = array(aList)[myIndices]
>>> list(a)
['a', 'd', 'e']

In some cases this solution can be more convenient than list comprehension.

Solution 4 - Python

You could use map

map(aList.__getitem__, myIndices)

or operator.itemgetter

f = operator.itemgetter(*aList)
f(myIndices)

Solution 5 - Python

I wasn't happy with these solutions, so I created a Flexlist class that simply extends the list class, and allows for flexible indexing by integer, slice or index-list:

class Flexlist(list):
    def __getitem__(self, keys):
        if isinstance(keys, (int, slice)): return list.__getitem__(self, keys)
        return [self[k] for k in keys]

Then, for your example, you could use it with:

aList = Flexlist(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
myIndices = [0, 3, 4]
vals = aList[myIndices]

print(vals)  # ['a', 'd', 'e']

Solution 6 - Python

If you do not require a list with simultaneous access to all elements, but just wish to use all the items in the sub-list iteratively (or pass them to something that will), its more efficient to use a generator expression rather than list comprehension:

(aList[i] for i in myIndices) 

Solution 7 - Python

Alternatively, you could go with functional approach using map and a lambda function.

>>> list(map(lambda i: aList[i], myIndices))
['a', 'd', 'e']

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRicky RobinsonView Question on Stackoverflow
Solution 1 - PythonValdir Stumm JuniorView Answer on Stackoverflow
Solution 2 - PythonjamylakView Answer on Stackoverflow
Solution 3 - PythonMarcin WojnarskiView Answer on Stackoverflow
Solution 4 - PythonwenzulView Answer on Stackoverflow
Solution 5 - PythonjedwardsView Answer on Stackoverflow
Solution 6 - PythonwatsonicView Answer on Stackoverflow
Solution 7 - PythonkabirbaidhyaView Answer on Stackoverflow