154

Haskellで次のようなことを達成するための最も慣用的な方法は何ですか:

foldl (+) 0 [1,2,3,4,5]
--> 15

または、Ruby で同等のもの:

[1,2,3,4,5].inject(0) {|m,x| m + x}
#> 15

明らかに、Pythonはreduce上記とまったく同じようにfoldの実装である関数を提供しますが、プログラミングの「pythonic」方法は、lambda用語と高階関数を避け、可能な場合はリスト内包表記を優先することであると言われました。reduceしたがって、関数ではないPythonのリストまたはリストのような構造を折りたたむ好ましい方法はありますか、それともreduceこれを達成する慣用的な方法ですか?

4

8 に答える 8

147

配列を合計する Pythonic の方法は、 を使用してsumいます。reduce他の目的のために、 (functoolsモジュールからの) とモジュールの組み合わせを使用できる場合がありますoperator

def product(xs):
    return reduce(operator.mul, xs, 1)

Haskell 用語では、reduce実際には, であることに注意してください。foldl折り畳みを実行するための特別な構文はなく、 builtin もありませんfoldr。実際reduceに非結合演算子を使用することは、悪いスタイルと見なされます。

高階関数の使用は非常に Pythonic です。関数やクラスを含め、すべてがオブジェクトであるという Python の原則をうまく利用しています。ラムダ式が一部の Pythonista に眉をひそめられているのはあなたの言うとおりですが、主な理由は、ラムダ式が複雑になるとあまり読みにくくなる傾向があるためです。

于 2012-04-28T18:35:51.123 に答える
6

車輪を再発明することもできます。

def fold(f, l, a):
    """
    f: the function to apply
    l: the list to fold
    a: the accumulator, who is also the 'zero' on the first call
    """ 
    return a if(len(l) == 0) else fold(f, l[1:], f(a, l[0]))

print "Sum:", fold(lambda x, y : x+y, [1,2,3,4,5], 0)

print "Any:", fold(lambda x, y : x or y, [False, True, False], False)

print "All:", fold(lambda x, y : x and y, [False, True, False], True)

# Prove that result can be of a different type of the list's elements
print "Count(x==True):", 
print fold(lambda x, y : x+1 if(y) else x, [False, True, True], 0)
于 2013-05-21T09:39:01.277 に答える
1

この (reduce) 問題に対する実際の答えは、次のとおりです。ループを使用するだけです。

initial_value = 0
for x in the_list:
    initial_value += x #or any function.

これは reduce よりも高速であり、PyPy のようなものはそのようなループを最適化できます。

ところで、合計ケースはsum関数で解決する必要があります

于 2012-04-28T18:45:41.743 に答える