01 / 07
今度は絞りこみ
map は全部に同じ処理をかけるものだった。今度はいるものだけ残すほうだよ。
内包表記なら、うしろに if を足すんだったね。これと同じことをする組み込みの関数が filter(フィルター)だ。
kazus = [3, -1, 5, -2]print([x for x in kazus if x > 0])実行結果
[3, 5]
高階関数とラムダ式
INPUT · スライド
01 / 07
map は全部に同じ処理をかけるものだった。今度はいるものだけ残すほうだよ。
内包表記なら、うしろに if を足すんだったね。これと同じことをする組み込みの関数が filter(フィルター)だ。
kazus = [3, -1, 5, -2]print([x for x in kazus if x > 0])実行結果
[3, 5]
02 / 07
filter にも関数と回せるものの2つを渡す。ただし渡す関数の役割が map とは違うよ。
map に渡す関数 … 作り変えたものを返すfilter に渡す関数 … 残すかどうかを返すつまり True か False を返す関数を書く。そして返ってくるのは、map のときと同じくリストではないよ。
def seisuu(x): return x > 0kazus = [3, -1, 5, -2]f = filter(seisuu, kazus)print(type(f))実行結果
<class 'filter'>
03 / 07
落とし穴も map とまったく同じ。そのまま print しても中身は出てこない。
kazus = [3, -1, 5, -2]print(filter(seisuu, kazus))<filter object at 0x1234abcd>うしろの番地は実行するたびに変わる。そしてこれもエラーではない。静かに読めないものが出てくるだけだよ。
filter も「これから絞りますよ」という予約票。頼まれてはじめて1つずつ確かめるんだ。
04 / 07
解決も同じ。list(...) を通すだけだよ。
filter に渡した関数が True を返したものだけが残る。False を返したものは新しい並びに入らないので、元より短くなるのがふつうだよ。
def seisuu(x): return x > 0kazus = [3, -1, 5, -2]print(list(filter(seisuu, kazus)))実行結果
[3, 5]
05 / 07
こちらも並べてみよう。結果はまったく同じだよ。
list(filter(lambda x: x > 0, kazus))[x for x in kazus if x > 0]内包表記のほうは lambda も list も要らない。だからPythonでは内包表記のほうが好まれることが多い——map のときとまったく同じ結論だね。
kazus = [3, -1, 5, -2]a = list(filter(lambda x: x > 0, kazus))b = [x for x in kazus if x > 0]print(a)print(b)print(a == b)実行結果
[3, 5] [3, 5] True
06 / 07
filter には、関数のかわりに None を渡せるという変わった書きかたがある。
そうすると「偽っぽい値を落とす」という意味になるよ。第1章でやったね。0・空の文字・None・False が偽っぽい値だった。
下の例では、空の文字だけが消えている。空欄の混ざったデータを掃除するのによく使われる形だよ。
mojis = ["あか", "", "あお", ""]print(list(filter(None, mojis)))実行結果
['あか', 'あお']
07 / 07
filter で絞ってから map で変換する、という重ねかたもできる。内側から順に読むのがコツだよ。
ただし見てのとおり、カッコが深くなって読みにくい。同じことを内包表記で書くと [x * 2 for x in kazus if x > 0] の1行で済む。
重ねるなら内包表記。これがPythonの標準的な感覚だよ。次のレッスンでは、渡す側から受け取る側に立場を変えよう。
kazus = [3, -1, 5, -2]print(list(map(lambda x: x * 2, filter(lambda x: x > 0, kazus))))実行結果
[6, 10]