fold - fold([lr]1?)?, reduce, Aggregate, accumulate
http://en.wikipedia.org/wiki/Fold_%28higher-order_function%29
Common Lispにはreduceという関数があり、これはSchemeやHaskellでいうところのfoldにあたります。
いわゆる畳み込み関数というやつで、『畳み込みする関数』と『その初期値』を使って、リストを1要素に集約します。これを使うとSUM関数を簡単に定義できます。
上記Wikipediaからの転載ですが、こんなのもあるのねえ、ということで各言語ごとリストアップ。
- Common Lisp
- (reduce #'func list :initial-value init-value)
- Python2.5
- reduce
- JavaScript1.8
-
.reduce(func, init) もちろんIEでは使えず。まあ、定義すりゃあいけるんですが。 - Ruby
- inject, reduce
- Haskell
- fold{l|r} 型がちゃんとしているのが気持ちいい。
- Erlang
- foldl, foldrで存在。
- OCaml
- fold_{left|right}
- C++
- std::accumulate(). 自分の環境では発見できなかった orz
- C#3.0
-
.Aggregate(init, func)
Javaにないorz
きっとApache Commonsを探せばあるんでしょうけど、Java自体には無かった。
きっとJava7~9ぐらいのLambdaサポートで出てくるんでしょうけれども。
まあ、それはそれとして。適当に作ってみる。
まず集約関数のインタフェースを定義します。*1
public interface Aggregator<L, R> { R aggregate(L l, R r); }
次に集約メソッドを定義します。まあ、ジェネリック型定義はこんなもんで妥当っぽいでしょう。
public class FoldImplementation { /** * {@link Iterable}を集約します。ま、別に{@link java.util.Iterator}を集約してもいいんだけど。 * * @param <L> * 集約されるリスト({@link Iterable})の型 * @param <R> * 集約後(あるいは集約初期値)の型 * @param func * 畳みこみする関数 * @param list * 集約対象リスト * @param init * 集約時の初期値 * @return 集約結果 */ public static <L, R> R foldl(final Aggregator<? super L, R> func, final Iterable<? extends L> list, final R init) { R aggregated = init; for (final L each : list) { aggregated = func.aggregate(each, aggregated); } return aggregated; } }
動かしてみよう。ということで積をとってみます。
import java.util.ArrayList; public final class Main { public static void main(String[] args) { int init = 1; Aggregator<Integer, Integer> product = new Aggregator<Integer, Integer>() { @Override public Integer aggregate(Integer l, Integer r) { return l * r; } }; ArrayList<Integer> list = new ArrayList<Integer>(); list.add(12); list.add(34); list.add(56); list.add(78); list.add(90); final int result = FoldImplementation.foldl(product, list, init); System.out.println(result); // 160392960 } }
*1:1メソッドのインタフェースの乱発ってオブジェクト指向に反してる??