4484

Given a list ["foo", "bar", "baz"] and an item in the list "bar", how do I get its index 1?

6
  • 17
    Are you returning: [1] The lowest index in case there are multiple instances of "bar", [2] All the indices of "bar"? Commented May 12, 2018 at 20:56
  • 8
    a) Is it guaranteed that item is in the list, or else how we should handle the error case? (return None/ raise ValueError) b) Are list entries guaranteed to be unique, and should we return the first index of a match, or all indexes? Commented May 21, 2018 at 6:20
  • 1
    View the answers with numpy integration, numpy arrays are far more efficient than Python lists. If the list is short it's no problem making a copy of it from a Python list, if it isn't then perhaps you should consider storing the elements in numpy array in the first place. Commented Jan 28, 2020 at 12:21
  • 1
    I’m voting to close this question (in protest) because there are already 42 undeleted answers (and 16 more deleted) for a simple, one-liner reference question that almost all have the same built-in function at their core (as they should, because it's the only reasonable and sane approach to the problem and everything surrounding it is just error-checking or creatively re-interpreting the specification, which still only leaves one other reasonable, sane approach to the expanded problem). Commented Dec 27, 2022 at 4:39
  • There is no realistic chance of a better approach becoming possible in future versions of Python, because the existing approach is already just calling a single, built-in method on the list - as simple as it gets. Commented Dec 27, 2022 at 4:40

47 Answers 47

1
2
4

I find this two solution is better and I tried it by myself

>>> expences = [2200, 2350, 2600, 2130, 2190] >>> 2000 in expences False >>> expences.index(2200) 0 >>> expences.index(2350) 1 >>> index = expences.index(2350) >>> expences[index] 2350 >>> try: ... print(expences.index(2100)) ... except ValueError as e: ... print(e) ... 2100 is not in list >>> 
Sign up to request clarification or add additional context in comments.

Comments

4

For those coming from another language like me, maybe with a simple loop it's easier to understand and use it:

mylist = [ "foo", "bar", "baz", "bar" ] for index, item in enumerate(mylist): if item == "bar": print(index, item) 

I am thankful for So what exactly does enumerate do?. That helped me to understand.

2 Comments

It's only an example to understand how you can find repeated items - enumerate helps to do it.
@ggorlen I understood you about newlist variable that I used to define the result of enumerate(mylist). That's why I cut that line and put enumerate function on loop. And it's better now. Remembering that all everything is an object in Python, but you can call enumerate as "built-in" function as official documentation does, of course. And, when I use enumerate to put a list in order, I continue having a list. Otherwise, you would need to call it a dictionary, which is not the case.
4

Try the following code:

["foo", "bar", "baz"].index("bar") 

Refer to Python List index().

1 Comment

this code will break if "bar" is not in the list, adding a try except clause is needed here
3

As indicated by @TerryA, many answers discuss how to find one index.

more_itertools is a third-party library with tools to locate multiple indices within an iterable.

Given

import more_itertools as mit iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"] 

Code

Find indices of multiple observations:

list(mit.locate(iterable, lambda x: x == "bar")) # [1, 5] 

Test multiple items:

list(mit.locate(iterable, lambda x: x in {"bar", "ham"})) # [1, 3, 5] 

See also more options with more_itertools.locate. Install via > pip install more_itertools.

Comments

3

Let’s give the name lst to the list that you have. One can convert the list lst to a numpy array. And, then use numpy.where to get the index of the chosen item in the list. Following is the way in which you will implement it.

import numpy as np lst = ["foo", "bar", "baz"] #lst: : 'list' data type print np.where( np.array(lst) == 'bar')[0][0] >>> 1 

1 Comment

Does not work if the item is an instance of a class
3

Amazingly, next's fallback value second parameter mentioned in this comment in a duplicate thread hasn't been shown here yet.

The basic .index() works well when you can compare whole objects, but it's common to need to search a list of objects or dicts for a particular item by a certain property, in which case a generator with a condition is the natural choice:

>>> users = [{"id": 2, "name": "foo"}, {"id": 3, "name": "bar"}] >>> target_id = 2 >>> found_user = next(x for x in users if x["id"] == target_id) >>> found_user {'id': 2, 'name': 'foo'} 

This stops at the first matching element and is reasonably succinct.

However, if no matching element is found, a StopIteration error is raised, which is a little awkward to deal with. Luckily, next offers a second parameter next(gen, default) fallback to provide a more natural, except-free control flow:

>>> found_user = next((x for x in users if x["id"] == target_id), None) >>> if not found_user: ... print("user not found") ... user not found 

This is a bit more verbose, but still fairly readable.

If an index is desired:

>>> found_idx = next((i for i, x in enumerate(users) if x["id"] == 1), None) >>> found_idx None >>> next((i for i, x in enumerate(users) if x["id"] == 3), None) 1 

As this comment points out, it may be best not to return the typical -1 for a missing index, since that's a valid index in Python. Raising is appropriate if None seems odd to return.

These are a bit verbose, but feel free to bury the code in a helper function if you're using it repeatedly, providing an arbitrary predicate.

>>> def find(it, pred): ... return next((x for x in it if pred(x)), None) ... >>> find(users, lambda user: user["id"] == 2) {'id': 2, 'name': 'foo'} >>> print(find(users, lambda user: user["id"] == 42)) None >>> find("foobAr", str.isupper) # works on any iterable! 'A' 

Comments

3

Use:

text = ["foo", "bar", "baz"] target = "bar" [index for index, value in enumerate(text) if value == target] 

For a small list of elements, this would work fine. However, if the list contains a large number of elements, it is better to apply a binary search with O(log n) runtime complexity.

1 Comment

You can only binary search if the list is sorted, and sorting is O(n log(n)).
1

using dictionary , where process the list first and then add the index to it

from collections import defaultdict index_dict = defaultdict(list) word_list = ['foo','bar','baz','bar','any', 'foo', 'much'] for word_index in range(len(word_list)) : index_dict[word_list[word_index]].append(word_index) word_index_to_find = 'foo' print(index_dict[word_index_to_find]) # output : [0, 5] 

Comments

1

One of the simplest ways to find the index of an element in a list is to do as follows

arr = ["foo", "bar", "baz"] el = "bar" try: index = arr.index(el) return index except: return 'element not found'

Comments

1

A Pythonic way would to use enumerate, but you can also use indexOf from the operator module. Please note that this will raise ValueError if b not in a.

>>> from operator import indexOf >>> >>> help(indexOf) Help on built-in function indexOf in module _operator: indexOf(a, b, /) Return the first index of b in a. >>> indexOf(("foo", "bar", "baz"), "bar") # with tuple 1 >>> indexOf(["foo", "bar", "baz"], "bar") # with list 1 

Comments

1

A function "indexof", similar to another languages that returns -1 if the element is not found, can be written like:

def indexof (obj, elem, offset=0): if elem in obj[offset:]: return offset + obj[offset:].index(elem) return -1 obj = ["foo", "bar", "baz", "foo"] print (indexof(obj, "not here")) print (indexof(obj, "baz")) print (indexof(obj, "foo", 1)) 

which returns

-1 2 3 

Or an optimized version for big lists

def indexof (obj, elem, offset=0): if offset == 0: # No need for a sublist if elem in obj: return obj.index(elem) return -1 sublist = obj[offset:] if elem in sublist: return offset + sublist.index(elem) return -1 

Comments

1

Certain structures in Python contains an index method that works beautifully to solve this question.

'oi tchau'.index('oi') # 0 ['oi','tchau'].index('oi') # 0 ('oi','tchau').index('oi') # 0 

References:

In lists

1 Comment

The three links are to the exact same URL. Is that intentional?
0

Simple option:

a = ["foo", "bar", "baz"] [i for i in range(len(a)) if a[i].find("bar") != -1] 

1 Comment

Not every element in the list is string.
0

One can use zip() function to get the index of the value in the list. The code could be;

list1 = ["foo","bar","baz"] for index,value in zip(range(0,len(list1)),list1): if value == "bar": print(index) 

2 Comments

zip(range(0,len(list1)),list1) is overkill when you could just do enumerate(list1)
the code is an overkill
0

Don't. If you absolutely need to, use the .index(item...) method on list. However, it takes linear time, and if you find yourself reaching for it, you are probably misusing lists to do something you should not do with them.

Most likely, you care either about 1) a two-way mapping between integers and items, or 2) about finding an item in a sorted list of items.

For the first one, use a pair of dictionaries. If you want a library that does this for you, use the bidict library.

For the second one, use methods that can properly make use of the fact that the list is sorted. Use the built-in bisect module in python.

If you find yourself wanting to insert items in a sorted list, you should also not use a sorted list. Either weaken the sorted requirement to a heap using the builtin heapq module, or use the sortedcontainers library.

It is bad practice to use a data structure that is not designed for what you want to do. Using one that matches the task you give it will both telegraph to the reader that you want to do that specific thing, and also make your solution a lot faster/more scalable in practice.

Comments

0

A simple solution in Python:

li1 = ["foo", "bar", "baz"] for i in range(len(li1)): if li1[i] == "bar": print(i) 

The data type of the list elements is irrelevant. Just replace the "bar" with the element you are looking for. We can also write a function for this as:

def indexfinder(element,lis): for i in range(len(lis)): if lis[i] == element: return i 

Comments

0

Here are different methods to find all occurrences of "bar" in a list, I have ranked by execution speed and usecase:

lst = ["foo", "bar", "baz"] item = "bar" 

itertools.compress (Fastest: ~0.026 s) Memory Efficient

from itertools import compress indices = list(compress(range(len(lst)), [val == item for val in lst])) 

List Comprehension (~0.018 s) readability and simplicity

indices = [i for i, v in enumerate(lst) if v == item] 

collections.deque (~0.053 s) Faster Append

from collections import deque indices = deque() for i, val in enumerate(lst): if val == item: indices.append(i) indices = list(indices) 

filter + lambda (~0.029 s) Functional Approach

indices = list(filter(lambda i: lst[i] == item, range(len(lst)))) 

NumPy (np.where) (~0.165 s) Faster for Large Lists

import numpy as np indices = np.where(np.array(lst) == item)[0].tolist() 

Pandas (pd.Series.index) (~9.475 s) Best for DataFrames & Large Datasets

import pandas as pd indices = pd.Series(lst).index[pd.Series(lst) == item].tolist() 

Output:

[1] 

5 Comments

There's no way the List Comprehension solution takes ~0.081s just to go through those three elements. How did you measure, exactly?
I have used Python’s timeit module and run it multiple times (e.g., 100,000 iterations to ensure meaningful benchmarking.) and compute the average execution time (Approximate). ex: import timeit timeit.timeit('code', setup='import_libraries', number=100000)
And which Python implementation/version? I was surprised by the listcomp being slower than compress and deque, so I now tried it myself and can't reproduce it. The listcomp takes me ~0.04s and the other two ~0.07s. With CPython 3.13.0.
My benchmark script for my previous comment.
I have python 3.12, I have corrected my response by recalculating, there was a typo, Thanks!
1
2

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.