Finding the index of an item in a list

后端 未结 30 3326
你的背包
你的背包 2020-11-21 05:28

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

相关标签:
30条回答
  • 2020-11-21 05:49

    And now, for something completely different...

    ... like confirming the existence of the item before getting the index. The nice thing about this approach is the function always returns a list of indices -- even if it is an empty list. It works with strings as well.

    def indices(l, val):
        """Always returns a list containing the indices of val in the_list"""
        retval = []
        last = 0
        while val in l[last:]:
                i = l[last:].index(val)
                retval.append(last + i)
                last += i + 1   
        return retval
    
    l = ['bar','foo','bar','baz','bar','bar']
    q = 'bar'
    print indices(l,q)
    print indices(l,'bat')
    print indices('abcdaababb','a')
    

    When pasted into an interactive python window:

    Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54) 
    [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> def indices(the_list, val):
    ...     """Always returns a list containing the indices of val in the_list"""
    ...     retval = []
    ...     last = 0
    ...     while val in the_list[last:]:
    ...             i = the_list[last:].index(val)
    ...             retval.append(last + i)
    ...             last += i + 1   
    ...     return retval
    ... 
    >>> l = ['bar','foo','bar','baz','bar','bar']
    >>> q = 'bar'
    >>> print indices(l,q)
    [0, 2, 4, 5]
    >>> print indices(l,'bat')
    []
    >>> print indices('abcdaababb','a')
    [0, 4, 5, 7]
    >>> 
    

    Update

    After another year of heads-down python development, I'm a bit embarrassed by my original answer, so to set the record straight, one can certainly use the above code; however, the much more idiomatic way to get the same behavior would be to use list comprehension, along with the enumerate() function.

    Something like this:

    def indices(l, val):
        """Always returns a list containing the indices of val in the_list"""
        return [index for index, value in enumerate(l) if value == val]
    
    l = ['bar','foo','bar','baz','bar','bar']
    q = 'bar'
    print indices(l,q)
    print indices(l,'bat')
    print indices('abcdaababb','a')
    

    Which, when pasted into an interactive python window yields:

    Python 2.7.14 |Anaconda, Inc.| (default, Dec  7 2017, 11:07:58) 
    [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> def indices(l, val):
    ...     """Always returns a list containing the indices of val in the_list"""
    ...     return [index for index, value in enumerate(l) if value == val]
    ... 
    >>> l = ['bar','foo','bar','baz','bar','bar']
    >>> q = 'bar'
    >>> print indices(l,q)
    [0, 2, 4, 5]
    >>> print indices(l,'bat')
    []
    >>> print indices('abcdaababb','a')
    [0, 4, 5, 7]
    >>> 
    

    And now, after reviewing this question and all the answers, I realize that this is exactly what FMc suggested in his earlier answer. At the time I originally answered this question, I didn't even see that answer, because I didn't understand it. I hope that my somewhat more verbose example will aid understanding.

    If the single line of code above still doesn't make sense to you, I highly recommend you Google 'python list comprehension' and take a few minutes to familiarize yourself. It's just one of the many powerful features that make it a joy to use Python to develop code.

    0 讨论(0)
  • 2020-11-21 05:49

    If performance is of concern:

    It is mentioned in numerous answers that the built-in method of list.index(item) method is an O(n) algorithm. It is fine if you need to perform this once. But if you need to access the indices of elements a number of times, it makes more sense to first create a dictionary (O(n)) of item-index pairs, and then access the index at O(1) every time you need it.

    If you are sure that the items in your list are never repeated, you can easily:

    myList = ["foo", "bar", "baz"]
    
    # Create the dictionary
    myDict = dict((e,i) for i,e in enumerate(myList))
    
    # Lookup
    myDict["bar"] # Returns 1
    # myDict.get("blah") if you don't want an error to be raised if element not found.
    

    If you may have duplicate elements, and need to return all of their indices:

    from collections import defaultdict as dd
    myList = ["foo", "bar", "bar", "baz", "foo"]
    
    # Create the dictionary
    myDict = dd(list)
    for i,e in enumerate(myList):
        myDict[e].append(i)
    
    # Lookup
    myDict["foo"] # Returns [0, 4]
    
    0 讨论(0)
  • 2020-11-21 05:50

    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.

    0 讨论(0)
  • 2020-11-21 05:52

    If you are going to find an index once then using "index" method is fine. However, if you are going to search your data more than once then I recommend using bisect module. Keep in mind that using bisect module data must be sorted. So you sort data once and then you can use bisect. Using bisect module on my machine is about 20 times faster than using index method.

    Here is an example of code using Python 3.8 and above syntax:

    import bisect
    from timeit import timeit
    
    def bisect_search(container, value):
        return (
          index 
          if (index := bisect.bisect_left(container, value)) < len(container) 
          and container[index] == value else -1
        )
    
    data = list(range(1000))
    # value to search
    value = 666
    
    # times to test
    ttt = 1000
    
    t1 = timeit(lambda: data.index(value), number=ttt)
    t2 = timeit(lambda: bisect_search(data, value), number=ttt)
    
    print(f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")
    

    Output:

    t1=0.0400, t2=0.0020, diffs t1/t2=19.60
    
    0 讨论(0)
  • 2020-11-21 05:54
    name ="bar"
    list = [["foo", 1], ["bar", 2], ["baz", 3]]
    new_list=[]
    for item in list:
        new_list.append(item[0])
    print(new_list)
    try:
        location= new_list.index(name)
    except:
        location=-1
    print (location)
    

    This accounts for if the string is not in the list too, if it isn't in the list then location = -1

    0 讨论(0)
  • 2020-11-21 05:54

    Python index() method throws an error if the item was not found. So instead you can make it similar to the indexOf() function of JavaScript which returns -1 if the item was not found:

    try:
        index = array.index('search_keyword')
    except ValueError:
        index = -1
    
    0 讨论(0)
提交回复
热议问题