.NET 9 Preview 1 で追加された LINQ メソッドを書いてみています。
rksoftware.hatenablog.com
その中で前回、.AggregateBy
でちょっと特殊な使い方をしたくて迷っていました。今回はそこを少し深く語ってみます。
■ これまで .Aggregate
でよくやっていたこと
ループのそれまでの処理を踏まえる複雑な処理で list へ Add するようなコードを書きたい場合、次のようなコードが結構あると思います。
char[] t = ['a', 'b', 'a', 'a', 'b', 'c'];
{
List<char> list = new ();
foreach (var c in t)
{
list.Add(c);
}
Console.WriteLine(string.Join(", ", list));
}
そこで私は次のようなコードを書いてしまっていました。
char[] t = ['a', 'b', 'a', 'a', 'b', 'c'];
{
List<char> list = t.Aggregate(new List<char>(), (list, c) => { list.Add(c); return list; });
Console.WriteLine(string.Join(", ", list));
}
■ .AggregateBy
の場合
基本的にはこういう値型で使うのだと思います。
char[] t = ['a', 'b', 'a', 'a', 'b', 'c'];
{
IEnumerable<KeyValuePair<char, string>> m = t.AggregateBy(x => x, "", (s, x) => x + s);
Console.WriteLine(string.Join(", ", m.Select(x => $"{x.Key}: {x.Value}")));
}
ここで何も考えずに私がよく書いてしまう List<T>
に足していくコードを書いた場合には、意図通りではない結果になります。でもこれが仕様通りだと思います。
char[] t = ['a', 'b', 'a', 'a', 'b', 'c'];
{
IEnumerable<KeyValuePair<char, List<char>>> m = t.AggregateBy(x => x, new List<char>(), (s, x) => { s.Add(x); return s; });
Console.WriteLine(string.Join(", ", m.Select(x => $"{x.Key}: {string.Join("", x.Value)}")));
}
でも、諦めきれないので考えました。しかしこんなコードいいのか迷います。
char[] t = ['a', 'b', 'a', 'a', 'b', 'c'];
{
IEnumerable<KeyValuePair<char, List<char>>> m = t.AggregateBy(x => x, (List<char>?)null, (s, x) => { (s = s ?? new List<char>()).Add(x); return s; })!;
Console.WriteLine(string.Join(", ", m.Select(x => $"{x.Key}: {string.Join("", x.Value)}")));
}
■ でもよさそう
でも、新しい LINQ メソッドいいですよね。今回書いている .AggregateBy
メソッドも使いこなしていきたいです。そなえよう。