問題描述
你有一個資料序列,想利用一些規則從中提取出需要的值或是縮短的序列,
解決方案
最簡答的過濾序列元素的方法就是使用串列推導式,比如:
mylist = [1, 4, -5, 10, -7, 2, 3, -1]
res = [n for n in mylist if n > 0]
"""
res = [1, 4, 10, 2, 3]
"""
如果你對記憶體比較敏感,可以使用生成器運算式迭代產生過濾的元素,比如:
gen = (n for n in mylist if n > 0)
print(gen)
""" 輸出結果:
<generator object <genexpr> at 0x000001E4C8796CF0>
"""
for i in gen:
print(i)
""" 輸出結果:
1
4
10
2
3
"""
有時候過濾規則比較復雜,不能簡單的在串列推導式或者生成器運算式中表達出來,比如,過濾的時候需要處理一些例外或其他復雜情況,這時候你可以將過濾代碼封裝到一個函式中,然后使用內置函式filter(),例如:
values = ['1', '2', '-3', '-', '4', 'N/A', '5']
def is_int(v):
try:
x = int(v)
return True
except ValueError:
return False
res = list(filter(is_int, values))
print(res)
"""輸出結果:
['1', '2', '-3', '4', '5']
"""
需要注意,filter()函式創建的是一個迭代器,
討論
由官方檔案的介紹,串列推導式的方括號內包含以下內容:一個運算式,后面為一個for子句,然后是零個或多個for或if子句,結果是由運算式依據for和if子句求值計算而得出一個新串列,清楚了概念,再看下面幾個例子,
串列推導式和生成器運算式通常是過濾資料最簡單的方式,它們還能在過濾的時候轉換資料,例如:
import math
mylist = [1, 4, -5, 10, -7, 2, 3, -1]
res = [math.sqrt(n) for n in mylist if n > 0]
print(res)
"""輸出結果:
[1.0, 2.0, 3.1622776601683795, 1.4142135623730951, 1.7320508075688772]
"""
過濾操作的一個變種是將不符合條件的值用新的值替代,而不是丟掉它們,比如,你不僅想找到正數,還想將不是正數的數換成0,通過將過濾條件放到條件運算式中,就可以很容易地解決這個問題:
res = [n if n > 0 else 0 for n in mylist]
"""
res = [1, 4, 0, 10, 0, 2, 3, 0]
"""
res = [n if n < 0 else 0 for n in mylist]
"""
res = [0, 0, -5, 0, -7, 0, 0, -1]
"""
另外一個值得關注的過濾工具就是itertools.compress(),它以一個iterable物件和一個相對應的Boolean選擇器序列作為輸入引數,然后輸出iterable物件中對應選擇器為True的元素,當你需要用另一個相關聯的序列來過濾某個序列的時候,這個函式是非常有用的,例如,你有如下兩組資料:
addresses = [
'5412 N CLARK',
'5148 N CLARK',
'5800 E 58TH',
'2122 N CLARK',
'5645 N RAVENSWOOD',
'1060 W ADDISON',
'4801 N BROADWAY',
'1039 W GRANVILLE',
]
counts = [ 0, 3, 10, 4, 1, 7, 6, 1]
這兩個序列的元素個數是相等的,也就是它們的元素可以是一一對應的關系,現在你想將對應count值大于5的地址值全部輸出,那么你可以:
for itertools import compress
more5 = [n > 5 for n in counts]
print(more5)
"""輸出結果:
[False, False, True, False, False, True, True, False]
"""
res = list(compress(addresses, more5))
print(res)
"""輸出結果:
['5800 E 58TH', '1060 W ADDISON', '4801 N BROADWAY']
"""
這里的關鍵點在于先創建一個Boolean序列,指示哪些元素符合條件,然后compress()函式根據這個序列去選擇輸出對應位置為True的元素,
和filter()函式類似,compress()回傳的也是一個迭代器,因此,如果你想得到一個串列,那么你需要使用list()來將結果轉換為串列型別,
總結
本節介紹了過濾序列元素的幾種方法,
最簡單的方法就是利用串列推導式,如果你對記憶體使用有要求,可以改用生成器運算式,如果過濾規則過于復雜,無法在串列推導式或生成器運算式中表達出來,可以使用內置函式filter(),
另外還介紹了一個過濾工具itertools.compress(),當你需要通過另一個相關聯的序列來過濾某個序列時,可以用到它,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/398419.html
標籤:其他
