官术网_书友最值得收藏!

3.1.5 過濾序列元素

在實際應用中,我們經常需要根據指定規則從序列中提取需要的值,或者根據規則縮短序列,即對序列做過濾。

最簡單的過濾序列元素的方法是使用列表推導,示例如下:


exp_list = [1, 4, -5, 10, -7, 2, 3, -1]
print([n for n in exp_list if n > 0])
print([n for n in exp_list if n < 0])

使用列表推導的一個潛在缺陷是,如果輸入非常大,會產生一個非常大的結果集,占用大量內存。如果對內存比較敏感,那么可以使用生成器表達式迭代產生過濾的元素,示例如下:


pos_items = (n for n in exp_list if n > 0)
for item in pos_items:
    print(item)

有時候,過濾規則比較復雜,如過濾的時候需要處理一些異常或者其他復雜情況,不能簡單地在列表推導或者生成器表達式中表達出來。這時可以將過濾代碼放到一個函數中,然后使用內置的filter()函數,示例如下:


val_list = ['1', '2', '-3', '-', '4', 'N/A', '5']
def is_int(val):
    try:
        int(val)
        return True
    except ValueError:
        return False
new_val_list = list(filter(is_int, val_list))
print(new_val_list)

filter()函數創建了一個迭代器,因此想得到列表的話,就得像示例那樣使用list()函數去轉換。

通常情況下,列表推導和生成器表達式是過濾數據最簡單的方式。它們還能在過濾的時候轉換數據,示例如下:


import math
print([math.sqrt(n) for n in exp_list if n > 0])

過濾操作的一個變種是將不符合條件的值用新的值代替,而不是丟棄它們。如在一列數據中可能不僅想找到正數,還想將不是正數的數替換成指定的數。通過將過濾條件放到條件表達式中去,可以很容易地解決這個問題,示例如下:


print([n if n > 0 else 0 for n in exp_list])
print([n if n < 0 else 0 for n in exp_list])

另外一個值得關注的過濾工具就是itertools.compress(),它以一個iterable對象和一個相對應的Boolean選擇器序列作為輸入參數,然后輸出iterable對象中對應選擇器為True的元素。當需要用另一個相關聯的序列來過濾某個序列的時候,這個函數是非常有用的,示例如下:


done_work = [
    'read book',
    'running',
    'work',
    'basketball',
    'table tennis',
    'bike',
    'read 20 pages',
    'running 5km',
]
counts = [ 0, 3, 10, 4, 1, 7, 6, 1]

現在想將那些對應count值大于5的地址全部輸出,可以這樣寫代碼:


from itertools import compress
more5 = [n > 5 for n in counts]
print(more5)
print(list(compress(done_work, more5)))

這里的關鍵點在于先創建一個Boolean序列指示哪些元素符合條件,然后通過compress()函數根據Boolean序列去選擇輸出對應位置為True的元素。

compress()函數返回的是一個迭代器。如果要得到一個列表,需要使用list()函數將結果轉換為列表類型。

主站蜘蛛池模板: 礼泉县| 鄂托克旗| 长海县| 三明市| 南岸区| 敦煌市| 黑山县| 兴和县| 新沂市| 郯城县| 樟树市| 镇原县| 景谷| 台东市| 曲水县| 汕头市| 始兴县| 嵊州市| 文水县| 关岭| 精河县| 通榆县| 肥乡县| 交口县| 阳高县| 康乐县| 祁东县| 明星| 中西区| 佛山市| 平武县| 建瓯市| 涿鹿县| 涪陵区| 榆中县| 金塔县| 榆树市| 蒙山县| 灌南县| 萨迦县| 兴化市|