我有一段代码,我试图确定是否有更快的方式来运行它。本质上,我有一个分隔符文件,我正在遍历这个文件以找到一组标志来解析数据。这些文件可能非常长,所以我试图找到一种快速的方法。
我试过的两种方法是列表理解和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