どうも~むるむるです~
今回の記事では「map, reduce, filter」について学んでいきたいと思います.
このシリーズではプログラミング初心者が最低限のPythonの知識を最短で身に着けることを目標としています.
このシリーズでは以下の順番でPythonの基本的な知識を学習していきます.
- Python:Anacondaインストールとhello world,簡単な計算,コメントアウト
- 変数について
- データ型:int, float, str, bool
- データ型:list, tuple, dict
- 条件分岐:if – else 文
- 繰り返し:for文,while文
- 関数の定義,呼び出し,ラムダ式
- クラス
- モジュールのインポート
- 例外処理:try, except, else, finally
- map, reduce, filter (この記事)
さて,早速本題に入りましょう.
いよいよこのシリーズもこの記事で最終回です.気合を入れていきましょう!
リストなどの複数の要素すべてに同じ処理を行いたい場合,毎回for文を書いても良いのですが,少し面倒です.
さらにPythonのfor文は遅いことで有名なので,何度も繰り返し処理をするときはfor文を使うことは避けられるのであれば避けた方が良いです.
そんなとき,使えるのが今回紹介するmap, reduce, filter関数です.
それぞれリストのようなイテラブルオブジェクトに使うことができ,簡単に各要素に繰り返し処理ができます.
以下に,map, reduce, filter関数の説明をまとめました.
map: リストの各要素を関数の引数として実行
reduce: リストの各要素に関数を適用してを一つにまとめる
filter: リストの各要素のうち、条件を満たすものを抜き出す
書き方:
map(関数,イテラブルオブジェクト)
reduce(関数,イテラブルオブジェクト)
filter(関数,イテラブルオブジェクト)
map関数
map関数は,リストなどの各要素すべてに処理を行うことができます.
例を見てみましょう.
def square(n): return n**2 list1 = [1, 2, 3, 4] maplist = map(square, list1) print(list(maplist)) ''' 出力結果: [1, 4, 9, 16] '''
まず関数「square」という,与えられた値を2乗して返す関数を定義します.
あとは,リスト「[1, 2, 3, 4]」のすべての要素を, 関数「square」に渡した結果をリストとして受け取りたいのでmap関数を使います.
注意したいのはmap関数は,そのままリストを返してくれるわけではなくmapオブジェクトを返してくるので,そのままprint関数で出力しても中身がわかりません.
出力されたmapオブジェクトの型を「list( )」で変換してあげるとリスト型になるので,print関数で出力すると中身が確認できます.
ラムダ式(無名関数)
上の例では,「square」という関数を定義してからmap関数に渡しましたが,map関数などに一度使うだけの関数をいちいち定義するのは面倒です.
そんなときによく使われるのがラムダ式です.以下のように書くことで,名前を付けて関数を定義せずとも関数と同じように使えるため無名関数とも呼びます.
以下のコードは上の例と同じことをしていますが,関数を定義していない分,コードが少しすっきりしています.
list1 = [1, 2, 3, 4] maplist2 = map(lambda x: x**2, list1) print(list(maplist2)) ''' 出力結果: [1, 4, 9, 16] '''
reduce関数
reduce関数は,リストなどの各要素を左から右に向かって関数を適用していき,最終的に要素数が1つになるまで続けます.
例を見てみた方がわかりやすいでしょう.
# reduce: ラムダ式使わない場合 from functools import reduce def tasu(a, b): return a + b list1 = [1, 2, 3, 4] reducelist = reduce(tasu, list1) print(reducelist) # reduce: ラムダ式使った場合 reducelist2 = reduce(lambda x, y: x + y, list1) print(reducelist2) ''' 10 10 '''
まずreduce関数は組み込み関数ではなく,functoolsモジュールの関数なので「from functools import reduce」としてインポートする必要があります.
上の例では,「tasu」という二つの引数を足した値を返すという関数を左からすべての要素に適用,つまり「1+ 2」のあとに「(1 + 2) + 3 」を行い,
「((1 + 2) + 3) + 4 」 という処理を行い,最終的に10を返しています.
map関数の時と同じく,ラムダ式を使って書くとコードがすっきりします.
filter関数
filter関数は,リストなどの各要素の中から条件を満たすものだけを抜き出します.
以下ではリストの内,filter関数を使って偶数だけを抜き出しています.
# filter: ラムダ式使わない場合 def iseven(n): return n % 2 == 0 list1 = [1, 2, 3, 4] filterlist = filter(iseven, list1) print(list(filterlist)) # filter: ラムダ式使った場合 filterlist2 = filter(lambda x: x%2 == 0, list1) print(list(filterlist2)) ''' [2, 4] [2, 4] '''
自分で定義したiseven関数は,引数を2で割った余りが0のときTrue,そうでない場合はFalseを返します.
この関数を使って,各要素を引数としたときにTrueを返すものだけをfilter関数を使って抜き出すことができます.
map関数の時と同様,filter関数もリスト型ではなくfilterオブジェクトを返してくるので,リストとして扱いたいときは「list( )」を使ってリスト型に変換してあげる必要があります.
確認クイズ
以下のコードで出力される値を考えてみてください.考えたら実際にコードを書いてみて当たっているか確認してみましょう.
li = [1, 2, 3, 4] map_li = list(map(lambda x: x**2, li)) fil_li = list(filter(lambda x: x % 2 == 1, map_li)) print(map_li) print(fil_li)
li2 = [3, 2, 1, 0] red_li = reduce(lambda x, y: x * y, li2) print(red_li)