Symfoware

Symfowareについての考察blog

Pythonのmap,reduce

Pythonの組み込み関数、mapとreduceについてよく忘れるのでメモ。



map




map(function, iterable, ...)



iterable内全ての要素にfunctionを適用した結果のリストを返します。



  1. l = [1, 2, 3]
  2. #リスト内の値全てに1を足す
  3. ret = map(lambda item : item + 1, l)
  4. print(ret)




$ python sample.py
[2, 3, 4]





iterableの引数は複数取れます。
最初のfunctionはlistの数だけ引数を取る必要があります。


  1. l1 = [1, 2, 3]
  2. l2 = [10, 20, 30]
  3. #リスト1とリスト2の値を加えたリストを作成
  4. ret = map(lambda item1, item2 : item1 + item2, l1, l2)
  5. print(ret)




$ python sample.py
[11, 22, 33]





渡したリストの要素数が異なる場合はエラーというか、かけている箇所はNoneが渡されます。


  1. l1 = [1, 2]
  2. l2 = [10, 20, 30]
  3. #リスト1とリスト2の値を加えたリストを作成
  4. ret = map(lambda item1, item2 : item1 + item2, l1, l2)
  5. print(ret)





$ python sample.py
Traceback (most recent call last):
File "sample.py", line 7, in <module>
    ret = map(lambda item1, item2 : item1 + item2, l1, l2)
File "sample.py", line 7, in <lambda>
    ret = map(lambda item1, item2 : item1 + item2, l1, l2)
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'





iterableであればよいので、辞書型も渡せます。


  1. l = [1, 2]
  2. m = {'key_1':'value_1', 'key_2':'value_2'}
  3. #リストとマップのキーを結合
  4. ret = map(lambda item1, item2 : str(item1) + '-' + item2, l, m)
  5. print(ret)




$ python sample.py
['1-key_1', '2-key_2']





辞書型のiteritemsを渡すことも可能。
その場合、functionに渡されるのはタプルになります。


  1. l = [1, 2]
  2. m = {'key_1':'value_1', 'key_2':'value_2'}
  3. #リストとマップのキーを結合
  4. ret = map(lambda item1, item2 : str(item1) + '-' + item2[0] + '-' + item2[1], l, m.iteritems())
  5. print(ret)




$ python sample.py
['1-key_1-value_1', '2-key_2-value_2']




タプルで渡されるのでこういう書き方でももちろんOK。


  1. l = [1, 2]
  2. m = {'key_1':'value_1', 'key_2':'value_2'}
  3. #リストとマップのキーを結合
  4. ret = map(lambda item1, (item2, item3) : str(item1) + '-' + item2 + '-' + item3, l, m.iteritems())
  5. print(ret)






応用として、groovyとかでいうcollectみたいな使い方も可能です。


  1. class myObj(object):
  2.     
  3.     def set_value(self, item):
  4.         self.item = item
  5.     
  6.     def get_value(self):
  7.         return self.item
  8.     
  9.     def calc(self):
  10.         self.item += 10
  11.     
  12. l = []
  13. obj = myObj()
  14. obj.set_value(1)
  15. l.append(obj)
  16. obj = myObj()
  17. obj.set_value(2)
  18. l.append(obj)
  19. #リストに入っているオブジェクト全てのcalcメソッドを呼び出す
  20. map(lambda item : item.calc(), l)
  21. for obj in l:
  22.     print(obj.get_value())




$ python sample.py
11
12









reduce




reduce(function, iterable[, initializer])



reduceは、iterableの要素に対して順に、直前の演算結果を持ちながら値を適用していきます。


例えばこんなソース。


  1. l = [1, 2, 3]
  2. ret = reduce(lambda x, y : x + y, l)
  3. print(ret)




これは((1 + 2) + 3)と同等です。


$ python sample.py
6





わかりやすさのため、演算途中を表示するようにしてみます。


  1. def hook(x, y):
  2.     print(x,y)
  3.     return x + y
  4. l = [1, 2, 3, 4, 5]
  5. ret = reduce(hook, l)
  6. print('------')
  7. print(ret)




$ python sample.py
1 2
3 3
6 4
10 5
15





$ python sample.py
(1, 2)
(3, 3)
(6, 4)
(10, 5)
------
15




第三引数を指定すると、それが初期値として使用されます。


  1. def hook(x, y):
  2.     print(x,y)
  3.     return x + y
  4. l = [1, 2, 3, 4, 5]
  5. ret = reduce(hook, l, 100)
  6. print('------')
  7. print(ret)




$ python sample.py
(100, 1)
(101, 2)
(103, 3)
(106, 4)
(110, 5)
------
115






別に演算結果を返す必要は無いので、例えばリスト内の最大値を返すとかでも問題ないです。



  1. def hook(x, y):
  2.     return max(x, y)
  3. l = [1, 2, 3, 4, 5, 4, 3 ,2, 1]
  4. ret = reduce(hook, l)
  5. print(ret)




$ python sample.py
5




まあ、そもそもmaxはこんな感じで引数にリストをとれるので、上記のプログラムに意味は無いですがサンプルとして。


  1. l = [1, 2, 3, 4, 5, 4, 3 ,2, 1]
  2. print(max(l))




$ python sample.py
5


関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2013/12/30(月) 21:31:55|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<Apache Spark spark-shell起動時のログの警告に対処する(log4j.properties) | ホーム | Pythonでリスト、ディクショナリーの便利なループ方法(enumerate,iteritems,zip)>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1191-2f9ee2d5
この記事にトラックバックする(FC2ブログユーザー)