How to find the index of the nth time an item appears in a list?
Asked Answered
Z

7

32

Given:

x = ['w', 'e', 's', 's', 's', 'z','z', 's']

Each occurrence of s appears at the following indices:

1st: 2
2nd: 3
3rd: 4
4th: 7

If I do x.index('s') I will get the 1st index.

How do I get the index of the 4th s?

Zilber answered 8/3, 2014 at 8:56 Comment(1)
probably duplicate of #1884480Blinny
T
34

Using list comprehension and enumerate:

>>> x = [ 'w', 'e', 's', 's', 's', 'z','z', 's']
>>> [i for i, n in enumerate(x) if n == 's'][0]
2
>>> [i for i, n in enumerate(x) if n == 's'][1]
3
>>> [i for i, n in enumerate(x) if n == 's'][2]
4
>>> [i for i, n in enumerate(x) if n == 's'][3]
7
Trevelyan answered 8/3, 2014 at 8:58 Comment(0)
F
11

If you didn't want to store the indices for each occurrence, or wanted to work with arbitrary iterables then something like:

from itertools import islice

def nth_index(iterable, value, n):
    matches = (idx for idx, val in enumerate(iterable) if val == value)
    return next(islice(matches, n-1, n), None)

x = [ 'w', 'e', 's', 's', 's', 'z','z', 's']
idx = nth_index(x, 's', 4)
# 7

Note there's a default value of None there in the next. You may wish to change that to something else, or remove it and catch the StopIteration and raise as another more suitable exception (ValueError for instance, so that it ties up more with list.index behaviour).

Fourscore answered 8/3, 2014 at 9:5 Comment(0)
A
4

For getting the index of the items:

return [index for index, char in enumerate(x) if char == 's']

For getting the character itself:

return [char for index, char in enumerate(x) if char == 's']

Or to get tuples of character/index pairs: (Thanks to falsetru for pointing out a simpler solution)

pairs = [(index, char) for index, char in enumerate(x) if char == 's']
Adoree answered 8/3, 2014 at 8:59 Comment(3)
enumerate yields index-element pairs, not element-index pairs. And [char, index for ...] causes a SytnaxError.Trevelyan
oops my bad, let me fix thatAdoree
The last code can be replaced with pairs = [(index, char) for index, char in enumerate(x) if char == 's'] or pairs = [pair for pair in enumerate(x) if pair[1] == 's'].Trevelyan
B
1
def find_nth_character(str1, substr, n):
    """find the index of the nth substr in string str1""" 
    k = 0
    for index, c in enumerate(str1):
        #print index, c, n  # test
        if c == substr:
            k += 1
            if k == n:
                return index


str1 = "B.765.A87_43.Left.9878.xx8"
substr = '.'
occurance = 4

print "%s #%d at index %d" % (substr, occurance, find_nth_character(str1, substr, occurance))
Blinny answered 8/3, 2014 at 9:6 Comment(0)
T
0

Here is a more Pythonic approach using itertools.count and a generator expression:

In [24]: def get_nth_index(lst, item, n):
    ...:     c = count()
    ...:     return next(i for i, j in enumerate(x) if j=='s' and next(c) == n-1)

Demo:

In [25]: get_nth_index(x, 's', 2)
Out[25]: 3

In [26]: get_nth_index(x, 's', 3)
Out[26]: 4

In [27]: get_nth_index(x, 's', 4)
Out[27]: 7

In [28]: get_nth_index(x, 's', 5)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-28-fc4e5e8c31ef> in <module>()
----> 1 get_nth_index(x, 's', 5)

<ipython-input-24-5394f79b3c30> in get_nth_index(lst, item, n)
      1 def get_nth_index(lst, item, n):
      2     c = count()
----> 3     return next(i for i, j in enumerate(x) if j=='s' and next(c) == n-1)

StopIteration: 

In [29]: 

As you can see, it will raise an StopIteration exception in case it can't find a match. You can also pass a default argument to next() function to return a default value instead of raising exception.

Tensor answered 26/3, 2018 at 6:14 Comment(1)
In your function definition, you use x instead of the lst argument. This is a mistake. Solid solution otherwise though.Blamable
P
0

simply we can extend the functionality of the built-in list class. by inheriting it.

In [64]: class List(list):
       :     def __init__(self, *val):
       :         self.extend(list(val))
       :
       :
       :     def findidx(self, val, n=None):
       :         '''return the occurances of an object in a list'''
       :
       :         if n == None:
       :             return [i for i, v in enumerate(self) if v == val]
       :
       :         return [i for i, v in enumerate(self) if v == val][n]

and there are two ways to use this class. see in the following example to understand.

In [65]: c = List(4, 5, 6, 7, 2, 5, 4 ,4) # enter the elements of the list as a argument

In [69]: c.findidx(4, 0) # search 4's 0th(1) occurance
Out[69]: 0

In [72]: c.findidx(4, 1) # find 4's 1st(2) occurance
Out[72]: 6

or

In [66]: c.findidx(4) # find all occurances of 4
Out[66]: [0, 6, 7]

In [67]: c.findidx(4)[0] # first occurance
Out[67]: 0

In [67]: c.findidx(4)[2] # third occurance
Out[67]: 7

In [69]: c[0]# for verification
Out[69]: 4

In [70]: c[7]
Out[70]: 4

`

Pageboy answered 8/8, 2019 at 8:16 Comment(0)
J
0

You can use this to find in last position

where a is the array

t=(a.index(0)+a.count(0))-1

You can increase the number to -2 or -3 to find the position of the desired number from last

NOTE: The list must be sorted. You can sort it with sort ()

eg: a.sort()

for more inbuilt function in list click here

Jaborandi answered 5/8, 2020 at 10:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.