Python:为什么多个列表理解似乎比一个带有if...elif语句的for循环要快?

问题描述 投票:2回答:1

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

我试过的两种方法是列表理解和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(),才导致速度变慢。

所以我想问一下,有没有更快的方法来实现这个问题?

python for-loop list-comprehension
1个回答
0
投票

没有任何数据样本或基准,很难重现你的观察。我试过用。

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
© www.soinside.com 2019 - 2024. All rights reserved.