4.8 跳過可迭代對(duì)象的開始部分

2018-02-24 15:26 更新

問題

你想遍歷一個(gè)可迭代對(duì)象,但是它開始的某些元素你并不感興趣,想跳過它們。

解決方案

itertools 模塊中有一些函數(shù)可以完成這個(gè)任務(wù)。首先介紹的是 itertools.dropwhile() 函數(shù)。使用時(shí),你給它傳遞一個(gè)函數(shù)對(duì)象和一個(gè)可迭代對(duì)象。它會(huì)返回一個(gè)迭代器對(duì)象,丟棄原有序列中直到函數(shù)返回True之前的所有元素,然后返回后面所有元素。

為了演示,假定你在讀取一個(gè)開始部分是幾行注釋的源文件。比如:

>>> with open('/etc/passwd') as f:
... for line in f:
...     print(line, end='')
...
##
# User Database
#
# Note that this file is consulted directly only when the system is running
# in single-user mode. At other times, this information is provided by
# Open Directory.
...
##
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
...
>>>

如果你想跳過開始部分的注釋行的話,可以這樣做:

>>> from itertools import dropwhile
>>> with open('/etc/passwd') as f:
...     for line in dropwhile(lambda line: line.startswith('#'), f):
...         print(line, end='')
...
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
...
>>>

這個(gè)例子是基于根據(jù)某個(gè)測試函數(shù)跳過開始的元素。如果你已經(jīng)明確知道了要跳過的元素的個(gè)數(shù)的話,那么可以使用 itertools.islice() 來代替。比如:

>>> from itertools import islice
>>> items = ['a', 'b', 'c', 1, 4, 10, 15]
>>> for x in islice(items, 3, None):
...     print(x)
...
1
4
10
15
>>>

在這個(gè)例子中,islice() 函數(shù)最后那個(gè) None 參數(shù)指定了你要獲取從第3個(gè)到最后的所有元素,如果 None 和3的位置對(duì)調(diào),意思就是僅僅獲取前三個(gè)元素恰恰相反,(這個(gè)跟切片的相反操作 [3:][:3] 原理是一樣的)。

討論

函數(shù) dropwhile()islice() 其實(shí)就是兩個(gè)幫助函數(shù),為的就是避免寫出下面這種冗余代碼:

with open('/etc/passwd') as f:
    # Skip over initial comments
    while True:
        line = next(f, '')
        if not line.startswith('#'):
            break

    # Process remaining lines
    while line:
        # Replace with useful processing
        print(line, end='')
        line = next(f, None)

跳過一個(gè)可迭代對(duì)象的開始部分跟通常的過濾是不同的。比如,上述代碼的第一個(gè)部分可能會(huì)這樣重寫:

with open('/etc/passwd') as f:
    lines = (line for line in f if not line.startswith('#'))
    for line in lines:
        print(line, end='')

這樣寫確實(shí)可以跳過開始部分的注釋行,但是同樣也會(huì)跳過文件中其他所有的注釋行。換句話講,我們的解決方案是僅僅跳過開始部分滿足測試條件的行,在那以后,所有的元素不再進(jìn)行測試和過濾了。

最后需要著重強(qiáng)調(diào)的一點(diǎn)是,本節(jié)的方案適用于所有可迭代對(duì)象,包括那些事先不能確定大小的,比如生成器,文件及其類似的對(duì)象。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)