python3x: hidden function, reduce, map

前から知っていたけどあまり使う機会のない関数だったのでせっかくなので休憩の合間に書いてみることにします。

#basics
基本の形は恐らくこんな感じ: `reduce(accum, lst, zero_val = None)`。python3以降を使っている人はbuilt_in_funcとして入ってはいないので呼び出すときは`from functools import reduce`で。簡単に言うと`lst`とから`x = lst[0]`を持ってきてそれを`accum(x, y)`と地道に処理を行い、結果をアウトプットする。基本的にアウトプットは1つ。

適当に[ネット上で見付けた](http://www.bogotobogo.com/python/python_fncs_map_filter_reduce.php)例: (refer to the link below for greater details)

```
>>> 
>>> from functools import reduce
>>> reduce( (lambda x, y: x * y), [1, 2, 3, 4] ) # 1*2*3*4
24
>>> reduce( (lambda x, y: x / y), [1, 2, 3, 4] ) # 1/2/3/4
0.041666666666666664
>>> 
```

for loop verで書くと以下のようになるらしい。

```
>>> L = [1, 2, 3, 4]
>>> result = L[0]
>>> for x in L[1:]:
	result = result * x	
>>> result
24
>>> 
```

for loopで見ると分かりやすい。`result`は予めpreset valとして決めておいてそこからリストの中の残りを全てかけていく。

独自に関数を作ると以下のようになるらしい:

```
>>> def myreduce(fnc, seq):
	tally = seq[0]
	for next in seq[1:]:
		tally = fnc(tally, next)
	return tally

>>> myreduce( (lambda x, y: x * y), [1, 2, 3, 4])
24
>>> myreduce( (lambda x, y: x / y), [1, 2, 3, 4])
0.041666666666666664
>>> 
```

#still feel the need to fiddle around with it?

strをinputとして扱うことも。

```
import functools
>>> L = ['Testing ', 'shows ', 'the ', 'presence', ', ','not ', 'the ', 'absence ', 'of ', 'bugs']
>>> functools.reduce( (lambda x,y:x+y), L)
'Testing shows the presence, not the absence of bugs'
>>> 
```

これは以下と同じ：

```
>>> ''.join(L)
'Testing shows the presence, not the absence of bugs'
```

```
>>> import functools, operator
>>> functools.reduce(operator.add, L)
'Testing shows the presence, not the absence of bugs'
>>> 
```

例えば`[[[1, 2, 3], [4, 5], [6, 7, 8]]]`を`[1,2,3,4,5,6,7,8]`に変えたい時、

```
>>> reduce(list.__add__, [[1, 2, 3], [4, 5], [6, 7, 8]], [])
[1,2,3,4,5,6,7,8]

>>> from operator import add
>>> reduce(add, [[[1, 2, 3], [4, 5], [6, 7, 8]]], [])
[1,2,3,4,5,6,7,8]

```

もしくは`[1, 2, 3, 4, 5, 6, 7, 8]`を`12345678`に変えた時

```
int("".join(map(str, [1,2,3,4,5,6,7,8]))) #ugly slow way they say lol

reduce(lambda a,d: 10*a+d, [1,2,3,4,5,6,7,8], 0) #pretty reduce way :)
```

#Map

<a href="http://postd.cc/an-introduction-to-functional-programming/" target="_blank">An introduction to Functional Programming</a>より。

```obj.py
import random
names = ["Taro", "Shinji", "Ryohei"]
code_names = ["Mr. Fink", "Mrs. Brown", "Mr. Steve"]

for i in range(len(names)):
    names[i] = random.choice(code_names) #grabs code_name out at random

print(names)
```

をmapを使ったfunctional programming風に書くと:

```fp.py
import random
names = ["Taro", "Shinji", "Ryohei"]
map(lambda i: random.choice(["Mr. Fink", "Mrs. Brown", "Mr. Steve"]), names)
```

`i`が`names`リストの中の要素インスタンスとなって名前を変えていく感じ。

>演習1. 以下のコードをmapとして書き換えてみましょう。このコードは本当の名前のリストを受け取り、より強力な戦略を用いて生み出されるコードネームと入れ替えます。

```
names = ['Mary', 'Isla', 'Sam']
 
for i in range(len(names)):
    names[i] = hash(names[i])
 
print names
# => [6306819796133686941, 8135353348168144921, -1228887169324443034]
```

答え:

```
names = ['Mary', 'Isla', 'Sam']

secret_names = map(hash, names)
```

#references

- [Python Functions map, filter, and reduce](http://www.bogotobogo.com/python/python_fncs_map_filter_reduce.php)
- [Useful code which uses reduce() in python [closed]](http://stackoverflow.com/questions/15995/useful-code-which-uses-reduce-in-python)