かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

関数的なMapReduceによる問題解決 via WEB+DB PRESS vol67

WEB+DB PRESS vol67が家に届いたのでぼちぼち読んでます。特集の所で「関数的なMapReduceによる問題解決」ということでHaskellを使ってMapとReduceで問題を解いてみようというのがありました。コードはこんな感じでした。

# via WEB+DB PRESS vol67
let ret1 = zip [0..] [10, 20, 30, 40, 50]
let mul (i, x) = x * i
let ret2 = map mul ret1
foldl (+) 0 ret2

これで結果が400になるという感じですね。ということでさくっとC#でも書いてみました。無限リスト作るのにGenerateメソッドがほしかったのでInteractive ExtensionsをNuGetで参照に追加しています。

namespace CSSample
{
    using System;
    using System.Linq;

    class Program
    {
        // Interactive Extensions
        static void Main(string[] args)
        {
            var ret = EnumerableEx
                // 無限リスト
                .Generate(0, _ => true, i => i + 1, i => i)
                // Tuple化
                .Zip(new[] { 10, 20, 30, 40, 50 }, Tuple.Create)
                // Map
                .Select(t => t.Item1 * t.Item2)
                // Reduce(Sumを使ったほうがいいけど、任意の集計という意味合いも
                // こめてAggregate使ってみた
                .Aggregate((i, j) => i + j);
            // 表示
            Console.WriteLine(ret);
        }
    }
}

いやはや、流石に簡潔さでは負けるとしても同じ概念でC#でも処理をかけるのは素晴らしいですね!因みに、LINQで書いてるので、この処理を並列化させることはとても簡単にできたりします。(こんな軽い処理だと意味無いけど)

var ret = EnumerableEx
    // 無限リスト
    .Generate(0, _ => true, i => i + 1, i => i)
    // Tuple化
    .Zip(new[] { 10, 20, 30, 40, 50 }, Tuple.Create)
    // 並列化
    .AsParallel()
    // Map
    .Select(t => t.Item1 * t.Item2)
    // Reduce(Sumを使ったほうがいいけど、任意の集計という意味合いも
    // こめてAggregate使ってみた
    .Aggregate((i, j) => i + j);

ここらへんLINQをベースに色んなことが出来るように機能拡張されていってるので、とりあえずLINQで書いておけば色々できるようになる日も近いかもしれない?というWEB+DB PRESSを読んでて思いついた雑感でした。

因みにこのプログラムは下記に置いてます。