迭代特定列表的最快方法?

sal*_*902 5 python performance list-comprehension list

假设我有一个列表:

list=['plu;ean;price;quantity','plu1;ean1;price1;quantity1']
Run Code Online (Sandbox Code Playgroud)

我想遍历列表+用“;”分割列表 并放置一个 if 子句,如下所示:

for item in list:
    split_item=item.split(";")
    if split_item[0] == "string_value" or split_item[1] == "string_value":
        do something.....
Run Code Online (Sandbox Code Playgroud)

我想知道,这是否是最快的方法?假设我的初始列表要大得多(有更多的列表项)。我尝试使用列表理解:

item=[item.split(";") for item in list if item.split(";")[0] == "string_value" or item.split(";")[1] == "string_value"]
Run Code Online (Sandbox Code Playgroud)

但这实际上给了我较慢的结果。第一种情况平均为 90 毫秒,而第二种情况平均为 130 毫秒。我做的列表理解错了吗?有没有更快的解决方案?

Vee*_*rac 1

编辑:事实证明,正则表达式缓存对竞争有点不公平。我的错。正则表达式仅快了一小部分。

如果您追求速度,hcwhsa 的答案应该足够好。如果您需要更多,请查看re

import re
from itertools import chain

lis = ['plu;ean;price;quantity'*1000, 'plu1;ean1;price1;quantity1'*100]*1000

matcher = re.compile('^(?:plu(?:;|$)|[^;]*;ean(?:;|$))').match
[l.split(';') for l in lis if matcher(l)]
Run Code Online (Sandbox Code Playgroud)

时间,对于大多数积极的结果(又名。split是缓慢的主要原因):

SETUP="
import re
from itertools import chain
matcher = re.compile('^(?:plu(?:;|$)|[^;]*;ean(?:;|$))').match

lis = ['plu1;ean1;price1;quantity1'+chr(i) for i in range(10000)] + ['plu;ean;price;quantity' for i in range(10000)]
"

python -m timeit -s "$SETUP" "[[x] + [y] + z.split(';') for x, y, z in (item.split(';', 2) for item in lis) if x== 'plu' or y=='ean']"
python -m timeit -s "$SETUP" "[l.split(';') for l in lis if matcher(l)]"
Run Code Online (Sandbox Code Playgroud)

我们发现我的速度更快一些。

10 loops, best of 3: 55 msec per loop
10 loops, best of 3: 49.5 msec per loop
Run Code Online (Sandbox Code Playgroud)

对于大多数负面结果(大多数内容都被过滤):

SETUP="
import re
from itertools import chain
matcher = re.compile('^(?:plu(?:;|$)|[^;]*;ean(?:;|$))').match

lis = ['plu1;ean1;price1;quantity1'+chr(i) for i in range(1000)] + ['plu;ean;price;quantity' for i in range(10000)]
"

python -m timeit -s "$SETUP" "[[x] + [y] + z.split(';') for x, y, z in (item.split(';', 2) for item in lis) if x== 'plu' or y=='ean']"
python -m timeit -s "$SETUP" "[l.split(';') for l in lis if matcher(l)]"
Run Code Online (Sandbox Code Playgroud)

领先优势稍高一些

10 loops, best of 3: 40.9 msec per loop
10 loops, best of 3: 35.7 msec per loop
Run Code Online (Sandbox Code Playgroud)

如果结果始终是唯一的,请使用

next([x] + [y] + z.split(';') for x, y, z in (item.split(';', 2) for item in lis) if x== 'plu' or y=='ean')
Run Code Online (Sandbox Code Playgroud)

或更快的正则表达式版本

next(filter(matcher, lis)).split(';')
Run Code Online (Sandbox Code Playgroud)

itertools.ifilter(在 Python 2 上使用)。

时间:

SETUP="
import re
from itertools import chain
matcher = re.compile('^(?:plu(?:;|$)|[^;]*;ean(?:;|$))').match

lis = ['plu1;ean1;price1;quantity1'+chr(i) for i in range(10000)] + ['plu;ean;price;quantity'] + ['plu1;ean1;price1;quantity1'+chr(i) for i in range(10000)]
"

python -m timeit -s "$SETUP" "[[x] + [y] + z.split(';') for x, y, z in (item.split(';', 2) for item in lis) if x== 'plu' or y=='ean']"
python -m timeit -s "$SETUP" "next([x] + [y] + z.split(';') for x, y, z in (item.split(';', 2) for item in lis) if x== 'plu' or y=='ean')"

python -m timeit -s "$SETUP" "[l.split(';') for l in lis if matcher(l)]"
python -m timeit -s "$SETUP" "next(filter(matcher, lis)).split(';')"
Run Code Online (Sandbox Code Playgroud)

结果:

10 loops, best of 3: 31.3 msec per loop
100 loops, best of 3: 15.2 msec per loop
10 loops, best of 3: 28.8 msec per loop
100 loops, best of 3: 14.1 msec per loop
Run Code Online (Sandbox Code Playgroud)

所以这对这两种方法都有很大的推动作用。