[英]Python: why is multiple list comprehensions seemingly faster than a single for loop with if...elif statements?
我有一些代码,我试图确定是否有更快的运行方法。 本质上,我有一个带分隔符的文件,我正在迭代该文件以找到一组标志来解析数据。 这些文件可能很长,所以我试图为此找到一种快速的方法。
我尝试过的两种方法是列表理解和 for 循环:
方法一:
flag_set_1 = [i for i,row in enumerate(data_file) if row[0] == flag_1]
flag_set_2 = [i for i,row in enumerate(data_file) if row[0] == flag_2]
flag_set_3 = [i for i,row in enumerate(data_file) if row[0] == flag_3]
flag_set_4 = [i for i,row in enumerate(data_file) if row[0] == flag_4]
方法二:
for i,row in enumerate(data_file):
if row[0] == flag_1:
flag_set_1.append(i)
elif row[0] == flag_2:
flag_set_2.append(i)
elif row[0] == flag_3:
flag_set_3.append(i)
elif row[0] == flag_4:
flag_set_4.append(i)
在这种情况下,我实际上期望列表理解会变慢。 认为方法 1 必须迭代 data_file 4 次,而方法 2 只需迭代一次。 我怀疑在方法 2 中使用 append() 是减慢速度的原因。
所以我问,有没有更快的方法来实现这个?
没有任何数据样本或基准,也很难重现您的观察结果。 我试过:
from random import randint
data_file = [[randint(0, 15) for _ in range(20)] for _ in range(100000)]
flag_1 = 1
flag_2 = 2
flag_3 = 3
flag_4 = 4
常规循环的速度是四个列表理解的两倍(参见下面的基准)。
如果你想提高这个过程的速度,你有几个线索。
如果flag_n
是字符串并且您确定row[0]
是每一row
中的其中一个,那么您可以检查一个字符而不是整个字符串。 例如:
flag_1 = "first flag"
flag_2 = "second flag"
flag_3 = "third flag"
flag_4 = "fourth flag"
查看第二个字符: f<I>rst, S<E>cond, T<H>ird, F<O>urth
。 您只需要检查row[0][1] == 'i'
(或'e'
或'h'
或'o'
)而不是row[0] == flag_n
。
如果你想提高常规循环的速度,你有几个线索。
您可以分配flag = row[0]
而不是四次获取row[0]
的第一个元素。 这是基本的,但它有效。
如果数据按标志排序,您显然可以立即构建flag_n_set
:找到第一个最后一个flag_n
并编写flag_n_set = list(range(first_flag_n_index, last_flag_n_index+1))
。
如果你知道标志的频率,你可以命令if... elif... elif... elif... else
首先检查更频繁的标志,然后是第二频繁的标志,等等。
您还可以使用 dict 来避免if... elif...
序列。 如果您没有太多与任何标志不匹配的行,则可以使用defaultdict
:
from collections import defaultdict
def test_append_default_dict():
flag_set = defaultdict(list)
for i, row in enumerate(data_file):
flag_set[row[0]].append(i)
return tuple(flag_set[f] for f in (flag_1, flag_2, flag_3, flag_4))
以上数据的基准:
test_list_comprehensions 3.8617278739984613
test_append 1.9978336450003553
test_append_default_dict 1.4595633919998363
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.