简体   繁体   English

在列表中查找项目索引的最快方法?

[英]Fastest way to find Indexes of item in list?

If one was to attempt to find the indexes of an item in a list you could do it a couple different ways here is what I know to be the fastest:如果要尝试在列表中查找项目的索引,您可以通过几种不同的方式来完成,这是我所知道的最快的方法:

aList = [123, 'xyz', 'zara','xyz', 'abc']; 
indices = [i for i, x in enumerate(aList) if x == "xyz"]
print(indices)

Another way not pythonic and slower:另一种不是pythonic且速度较慢的方法:

count = 0
indices = []
aList = [123, 'xyz', 'zara','xyz', 'abc'];
for i in range(0,len(aList):
    if 'xyz' == aList[i]:
        indices.append(i)
print(indices)

The first method is undoubtedly faster however what if you wanted to go faster, is there a way?第一种方法无疑更快,但是如果你想更快,有什么办法吗? For the first index using method:对于第一个索引使用方法:

aList = [123, 'xyz', 'zara','xyz', 'abc'];             
print "Index for xyz : ", aList.index( 'xyz' ) 

is very fast but can't handle multiple indexes.非常快,但不能处理多个索引。
How might one go about speeding things up?如何加快速度?

Use list.index(elem, start) !使用list.index(elem, start) That uses a for loop in C (see its implementation list_index_impl function in the source of CPython's listobject.c ).在 C 中使用for循环(请参阅 CPython 的listobject.c源代码中的实现list_index_impl函数)。 Avoid looping through all the elements in Python, it is slower than in C.避免循环遍历 Python 中的所有元素,它比 C 中慢。

def index_finder(lst, item):
    """A generator function, if you might not need all the indices"""
    start = 0
    while True:
        try:
            start = lst.index(item, start)
            yield start
            start += 1
        except ValueError:
            break

import array
def index_find_all(lst, item, results=None):
    """ If you want all the indices.
    Pass results=[] if you explicitly need a list,
    or anything that can .append(..)
    """
    if results is None:
        length = len(lst)
        results = (array.array('B') if length <= 2**8 else
                   array.array('H') if length <= 2**16 else
                   array.array('L') if length <= 2**32 else
                   array.array('Q'))
    start = 0
    while True:
        try:
            start = lst.index(item, start)
            results.append(start)
            start += 1
        except ValueError:
            return results

# Usage example
l = [1, 2, 3, 4, 5, 6, 7, 8] * 32

print(*index_finder(l, 1))
print(*index_find_all(l, 1))
def find(target, myList):
    for i in range(len(myList)):
        if myList[i] == target:
            yield i

def find_with_list(myList, target):
     inds = []
     for i in range(len(myList)):
         if myList[i] == target:
             inds += i,
     return inds


In [8]: x = range(50)*200
In [9]: %timeit [i for i,j in enumerate(x) if j == 3]
1000 loops, best of 3: 598 us per loop

In [10]: %timeit list(find(3,x))
1000 loops, best of 3: 607 us per loop
In [11]: %timeit find(3,x)
1000000 loops, best of 3: 375 ns per loop

In [55]: %timeit find_with_list(x,3)
1000 loops, best of 3: 618 us per loop

Assuming you want a list as your output:假设您想要一个列表作为输出:

  • All options seemed exhibit similar time performance for my test with the list comprehension being the fastest (barely).对于我的测试,所有选项似乎都表现出相似的时间性能,列表理解是最快的(勉强)。

If using a generator is acceptable, it's way faster than the other approaches.如果使用生成器是可以接受的,那么它比其他方法快得多。 Though it doesn't account for actually iterating over the indices, nor does it store them, so the indices cannot be iterated over a second time.虽然它不考虑实际迭代索引,也不存储它们,所以索引不能被第二次迭代。

Simply create a dictionary of item->index from the list of items using zip like so:只需使用 zip 从项目列表中创建一个 item->index 字典,如下所示:

items_as_dict = dict(zip(list_of_items,range(0,len(list_of_items))))
index = items_as_dict(item)

To get the index of the item, you can use the dictionary.要获取项目的索引,您可以使用字典。

aList = [123, 'xyz', 'zara','xyz', 'abc'];
#The following apporach works only on lists with unique values
aList = list(np.unique(aList)); 
dict = enumerate(aList);
# get inverse mapping of above dictionary, replace key with values
inv_dict = dict(zip(dict.values(),dict.keys()))
# to get index of item by value, use 'inv_dict' and to get value by index, use 'dict'
valueofItemAtIndex0 = dict[0]; # value = 123
indexofItemWithValue123 = inv_dict[123]; # index = 0
D=dict()
for i, item in enumerate(l):
    if item not in D:
        D[item] = [i]
    else:
        D[item].append(i)

Then simply call D[item] to get the indices that match.然后只需调用 D[item] 来获取匹配的索引。 You'll give up initial calculation time but gain it during call time.您将放弃初始计算时间,但会在调用期间获得它。

I used another way to find the index of a element in a list in Python 3:我使用另一种方法在 Python 3 的列表中查找元素的索引:

def index_of(elem, a):
    a_e = enumerate(a)
    a_f = list(filter(lambda x: x[1] == elem, a_e))
    if a_f:
        return a_f[0][0]
    else:
        return -1

Some tests:一些测试:

a=[1,2,3,4,2]
index_of(2,a)

This function always return the first occurrence of the element.这个函数总是返回元素的第一次出现。 If element ins't in the list, return -1.如果元素不在列表中,则返回 -1。 For my goals, that solution worked well.对于我的目标,该解决方案运行良好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM