閑古鳥

オールドプログラマの日記。プログラミングとか病気(透析)の話とか。

Enumerable.Aggregateの戻り値無し版が欲しいなぁと思ったという話

あまりいい例ではないのですが:

string[] arr = { "X", "Y", "Z" };
for (int i = 0; i < arr.Length - 1; ++i)
{
    Console.WriteLine("{0}, {1}", arr[i], arr[i + 1]);
}

これをLINQで書きたい。Aggregateメソッドを使うとシーケンスの現在の値とその次の値が取れるのですが、このメソッドは副作用を持てないので実現できない。どうしたものか。色々ググってみると、F#にはpairwiseという関数があるそうです。これを使うと先の配列を:

arr.Pairwise((x, y) => Tuple.Create(x, y));
// => [Tuple("X", "Y"), Tuple("Y", "Z")]

という風にまとめることができます。ここまでできれば……

arr.Pairwise((x, y) => Tuple.Create(x, y))
    .ForEach(t => Console.WriteLine("{0}, {1}", t.Item1, t.Item2));

できた!

なお、.NET Framework 4.0時点ではPairwiseもForEachも標準にはありませんので、今回はPairwiseはAchiral、ForEachはInteractive Extensionを利用させてもらいました。