かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

関数的な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を読んでて思いついた雑感でした。

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