在未排序列表的字符串列表中查找字符串的索引

时间:2018-11-27 18:32:29

标签: python list performance indexing

问题陈述

如果给定一个字符串,可以将其命名为target,能否将所有在某些输入字符串列表中找到target的索引都还给我(这很重要,它是字符串而不是数字),则将其称为input_list。输入示例:

target = '1234'
input_list = [str(x) for x in range(30000)] + [str(x) for x in range(30000)]

如果您要对列表进行排序,则不能假定input_list已排序,您需要将该列表添加到自己的benchmarkFind()版本中。简单的解决方案是只执行以下操作,但是效率可能很低:

def benchmarkFind(target,input_list):
    out = []
    for i in range(len(input_list)):
        if input_list[i] == target:
            out.append(i)
    return out

答案是:

idx = [1234, 31234]

基准测试结果

>>> %timeit benchmarkFind(target,input_list)
100 loops, best of 3: 3.07 ms per loop

用户评论结果

来自@trincot和@Abhinav Sood-稍微好一点,但不是很好。

def enumerateFind(target,input_list):
    return [i for i, e in enumerate(input_list) if e == target]

>>> %timeit enumerateFind(target,input_list)
100 loops, best of 3: 2.96 ms per loop

来自@B。 M-这似乎是迄今为止最好的答案

def primitiveFind(target ,input_list):
    try :
        l=[]
        u=-1
        while True:
            u = input_list.index(target,u+1)
            l.append(u)
    except ValueError:
        return l

>>> %timeit primitiveFind(target,input_list)
1000 loops, best of 3: 577 µs per loop

2 个答案:

答案 0 :(得分:1)

枚举速度更快:

python -m timeit -s "\
    target = '1234';\
    input_list = [str(x) for x in range(30000)] + [str(x) for x in range(30000)];\
    idx = [i for i, e in enumerate(input_list) if e == target]"

100000000次循环,最好是3次:每个循环 0.00582微秒

答案 1 :(得分:1)

众所周知,Python循环很慢,但列表中的原始循环很快。 def find2(target ,input_list): try : l=[] u=-1 while True: u= input_list.index(target,start=u+1) l.append(u) except ValueError: return l 很快。

In [32]: find2(target,input_list)
Out[32]: [1234, 31234]

In [33]: %timeit find2(target,input_list)
2.8 ms ± 255 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [34]: %timeit benchmarkFind(target,input_list)
12 ms ± 1.35 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [35]: %timeit [i for i, e in enumerate(input_list) if e == target]
14.2 ms ± 1.79 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

运行:

input_arr=np.array(input_list)

(input_arr==target).nonzero()
(array([ 1234, 31234], dtype=int64),)

%timeit input_arr=np.array(input_list)
10.6 ms ± 414 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit (input_arr==target).nonzero()
1.56 ms ± 123 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

今天早上我的计算机上快4倍。

编辑

对于进一步的调整,数据对齐很重要,numpy数组是实现此目的的好方法。不幸的是,从列表进行转换的成本很高,因此,如果可以以数组形式提供数据,这是有道理的:

with open("file.txt") as f:
    string = f.read()

formatted_string = string.replace("v ","")
formatted_string = formatted_string.replace("\n"," ")
str_numbers = formatted_string.split(" ")

with open("output.txt","w") as f:
    for i,num in enumerate(str_numbers):
        if i % 3 == 0:
            f.write(f"({float(num)},")
        elif i % 3 == 1:
            f.write(f" {float(num)},")
        else:
            f.write(f" {float(num)}), ")