高階関数とラムダ式

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 に条件を渡す

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 を通すと見える

解決も同じ。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

None を渡すと空っぽが落ちる

filter には、関数のかわりに None を渡せるという変わった書きかたがある。

そうすると「偽っぽい値を落とす」という意味になるよ。第1章でやったね。0・空の文字・None・False が偽っぽい値だった。

下の例では、空の文字だけが消えている。空欄の混ざったデータを掃除するのによく使われる形だよ。

mojis = ["あか", "", "あお", ""]print(list(filter(None, mojis)))

実行結果

['あか', 'あお']

07 / 07

map と組み合わせる

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]