簡體   English   中英

Python 中的列表切片與索引?

[英]List slicing vs indexing in Python?

我試圖用 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),但在這種情況下,我們只切片了字符串中的前兩個字符。 那么是什么導致它發生了戲劇性的變化呢?

索引的速度是切片的兩倍,但這是對非常小的數字的比較。 運行一百萬次時,差異約為 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)()

我正在更多地研究幕后發生的事情的細節,但根據Python Wiki ,索引具有恆定的時間復雜度 (O(1)),而切片的復雜度取決於切片的大小,O (k)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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