我試圖用 Python 處理一個檔案。長話短說,這里是我寫的代碼的兩個版本:
for line in file:
if line[0:2] == ".I":
#do something
elif line[0:2] == ".T":
#do something else
elif line[0:2] == ".A":
......
檔案中有大約 21000 行。但是,當我將代碼更改為以下內容時:
for line in file:
if line[0] == ".":
if line[1] == "I":
#do something
elif line[1] == "T":
#do something
elif line[1] == "A":
...
運行時間發生了巨大變化,我的意思是從 40 分鐘到 30 秒。我知道串列切片是 O(N),但在這種情況下,我們只切片了字串中的前兩個字符。那么是什么導致它發生了戲劇性的變化呢?
uj5u.com熱心網友回復:
索引的速度是切片的兩倍,但這是對非常小的數字的比較。運行一百萬次時,差異約為 0.04 秒。這不是您在代碼中看到的區別。
>>> timeit("s[0:2]=='aa'", setup="s = '12345'")
0.08988943499571178
>>> timeit("s[0]=='a'", setup="s = '12345'")
0.05322081400663592
>>> timeit("val=='aa'", setup="val='aa'")
0.03722755100170616
您可以通過將切片或索引值分配給變數一次并將其用于將來的比較來稍微加快這兩種情況。您也可以在參考區域變數的函式中執行此操作。
現在到了更大的問題。假設您有 10,000 行,其中 1000 行以“.”開頭。這些行均勻分布在“.A 和 .Z”之間。您將平均檢查 23 個不同的值。在第一種情況下,即 10000 * 23 或 230,000 次總檢查。在第二種情況下,您通過一次檢查消除了大多數候選者,然后用平均 23 次檢查消除了剩余的候選者。即 (9000) (1000 * 23) 或 32,000 次總檢查。檢查的條件減少了 86%。
讓我們走得更遠。假設您有不感興趣的“.whatever”值。這些值中的每一個都必須通過所有 26 項檢查,然后您才意識到它是無用的。如果是這種情況,您可以將所有比較器分組到一個集合中并首先檢查。
wanted = {".A", ".B", etc...)
for line in file:
check = line[:2]
if check in wanted:
val = check[1]
if ...
如果您可以將“do_something”代碼撰寫為函式,則可以走得更遠。
def do_thing_A():
pass
def do_thing_B():
pass
def do_nothing():
pass
do_all_the_things = {".A":do_thing_A, ".B":do_thing_B}
for line in file:
do_all_the_things.get(line[:2], do_nothing)()
uj5u.com熱心網友回復:
我正在更多地研究幕后發生的事情的細節,但根據Python Wiki,索引具有恒定的時間復雜度 (O(1)),而切片的復雜度取決于切片的大小,O (k)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/314371.html
上一篇:以十六進制格式處理時數字大小丟失
