Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding the indices of matching elements in list in Python

I have a long list of float numbers ranging from 1 to 5, called "average", and I want to return the list of indices for elements that are smaller than a or larger than b

def find(lst,a,b):     result = []     for x in lst:         if x<a or x>b:             i = lst.index(x)             result.append(i)     return result  matches = find(average,2,4) 

But surprisingly, the output for "matches" has a lot of repetitions in it, e.g. [2, 2, 10, 2, 2, 2, 19, 2, 10, 2, 2, 42, 2, 2, 10, 2, 2, 2, 10, 2, 2, ...].

Why is this happening?

like image 715
Logan Yang Avatar asked May 22 '13 07:05

Logan Yang


People also ask

How do you get the indices of all occurrences of an element in a list in Python?

One of the most basic ways to get the index positions of all occurrences of an element in a Python list is by using a for loop and the Python enumerate function. The enumerate function is used to iterate over an object and returns both the index and element.

How do I find the index of a character in a list?

How to Find the Index of a List Element in Python. You can use the index() method to find the index of the first element that matches with a given search object. The index() method returns the first occurrence of an element in the list. In the above example, it returns 1, as the first occurrence of “Bob” is at index 1.


2 Answers

You are using .index() which will only find the first occurrence of your value in the list. So if you have a value 1.0 at index 2, and at index 9, then .index(1.0) will always return 2, no matter how many times 1.0 occurs in the list.

Use enumerate() to add indices to your loop instead:

def find(lst, a, b):     result = []     for i, x in enumerate(lst):         if x<a or x>b:             result.append(i)     return result 

You can collapse this into a list comprehension:

def find(lst, a, b):     return [i for i, x in enumerate(lst) if x<a or x>b] 
like image 181
Martijn Pieters Avatar answered Sep 19 '22 07:09

Martijn Pieters


if you're doing a lot of this kind of thing you should consider using numpy.

In [56]: import random, numpy  In [57]: lst = numpy.array([random.uniform(0, 5) for _ in range(1000)]) # example list  In [58]: a, b = 1, 3  In [59]: numpy.flatnonzero((lst > a) & (lst < b))[:10] Out[59]: array([ 0, 12, 13, 15, 18, 19, 23, 24, 26, 29]) 

In response to Seanny123's question, I used this timing code:

import numpy, timeit, random  a, b = 1, 3  lst = numpy.array([random.uniform(0, 5) for _ in range(1000)])  def numpy_way():     numpy.flatnonzero((lst > 1) & (lst < 3))[:10]  def list_comprehension():     [e for e in lst if 1 < e < 3][:10]  print timeit.timeit(numpy_way) print timeit.timeit(list_comprehension) 

The numpy version is over 60 times faster.

like image 26
Alex Coventry Avatar answered Sep 18 '22 07:09

Alex Coventry