簡體   English   中英

Python:為什么多個列表理解似乎比使用 if...elif 語句的單個 for 循環更快?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM