python map/reduce/filter/sorted


pythonにはmap()とreduce()関数が組み込まれています.
map:
map()関数は2つのパラメータを受信し、1つは関数であり、もう1つはシーケンスであり、mapは入力した関数をシーケンスの各要素に順次作用させ、結果を新しいlistとして返す.
たとえば、list[1,2,3,4,5,6,7,8,9]にこの関数を作用させるには、map()を使用します.
>>> def f(x):
...     return x * x
...
>>> map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
[1, 4, 9, 16, 25, 36, 49, 64, 81]

map()が入力する最初のパラメータはf、すなわち関数オブジェクト自体であり、2番目のパラメータは実行するシーケンスである.
したがって、map()は高次関数として、実際には演算規則を抽象化しているので、簡単なf(x)=x 2を計算するだけでなく、このlistのすべての数字を文字列に変換するなど、任意の複雑な関数を計算することができます.
>>> map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])
['1', '2', '3', '4', '5', '6', '7', '8', '9']

 
Reduce:
reduceは1つの関数を1つのシーケンスに作用する[x 1,x 2,x 3...]で、この関数は2つのパラメータを受信する必要があります.reduceは結果をシーケンスの次の要素と累積計算し続けます.その効果は次のとおりです.
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4

たとえば、1つのシーケンスの和を求めると、reduceで実現できます.
>>> def add(x, y):
...     return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25

もちろん求和演算はPython内蔵関数sum()を直接用いることができ,reduceを用いる必要はない.しかし、シーケンス[1,3,5,7,9]を整数13579に変換すると、reduceが役に立ちます.
>>> def fn(x, y):
...     return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579

 
filter:
pythonに組み込まれたfilter()関数は、シーケンスをフィルタするために使用されます.
mapと同様に、filter()も関数とシーケンスを受信します.map()とは異なり、filter()は入力された関数を各要素に順次作用させ、戻り値がTrueかFalseかに基づいて要素を保持または破棄するかを決定します.
たとえば、listで偶数を削除し、奇数のみを保持します.
def is_odd(n):
    return n%2==1

filter(is_odd,[1,2,3,4,5,6,7,8,9,10,15])#  :[1,5,9,15]

1つのシーケンスの空の文字列を削除します.
def not_empty(s):
    return s and s.strip()

filter(not_empty, ['A', '', 'B', None, 'C', '  '])
#   : ['A', 'B', 'C']
filter()という高次関数を用いることがわかり、肝心なのは「フィルタ」関数を正しく実現することである.
 
sorted:
ソートもプログラムでよく使われるアルゴリズムです.バブルソートを使用しても高速ソートを使用しても、ソートのコアは2つの要素のサイズを比較することです.数字なら直接比較できますが、文字列か2つのdictなら?数学の大きさを直接比較するのは意味がないので,比較の過程は関数によって抽象化しなければならない.通常、2つの要素xとyについて、xyとすると1を返す、これにより、ソートアルゴリズムは具体的な比較過程に関心を持たず、比較結果に基づいて直接ソート.
Pyhonに内蔵されているsorted()関数はリストをソートできます.
>>> sorted([36, 5, 12, 9, 21])
[5, 9, 12, 21, 36]

さらにsorted()関数も高次関数であり、カスタムソートを実現するために比較関数を受信することもできます.たとえば、逆順序でソートする場合は、reversed_をカスタマイズできます.cmp関数:
def reversed_cmp(x, y):
    if x > y:
        return -1
    if x < y:
        return 1
    return 0

カスタム比較関数reversed_cmpを入力すると、逆順序ソートが可能になります.
>>> sorted([36, 5, 12, 9, 21], reversed_cmp)
[36, 21, 12, 9, 5]

文字列のソートの例を見てみましょう.
>>> sorted(['bob', 'about', 'Zoo', 'Credit'])
['Credit', 'Zoo', 'about', 'bob']

デフォルトでは、文字列のソートは、ASCIIのサイズで比較されます.'Z' < 'a'の結果、大文字Zが小文字aの前に表示されます.
次に、ソートは大文字と小文字を無視し、アルファベット順にソートすることを提案します.このアルゴリズムを実装するには、既存のコードを大きく変更する必要はありません.大文字と小文字を無視する比較アルゴリズムを定義できれば、次のことができます.
def cmp_ignore_case(s1, s2):
    u1 = s1.upper()
    u2 = s2.upper()
    if u1 < u2:
        return -1
    if u1 > u2:
        return 1
    return 0

大文字と小文字を無視して2つの文字列を比較するのは、実際には文字列を大文字(または小文字)にしてから比較します.
これにより、sortedに上記の比較関数を入力すると、大文字と小文字を無視したソートが実現されます.
>>> sorted(['bob', 'about', 'Zoo', 'Credit'], cmp_ignore_case)
['about', 'bob', 'Credit', 'Zoo']