C# LINQで左外部自己結合

static void Main(string[] args)
{
    // 連続して同じ値が来る箇所だけを省いて取得する
    // この場合だと1,2,4,3,4,0が取れることを目指す
    int[] array = { 1, 2, 4, 4, 3, 3, 4, 0, 0 };
    var arrayWithIndex = array.Select((value, index) => new { value, index });

    var result =
        from orig in arrayWithIndex
        join alias in arrayWithIndex on orig.index equals alias.index - 1 into _
        from alias in _.DefaultIfEmpty()
        where alias == null || orig.value != alias.value
        select orig.value;
}

前回に引き続いてindex生成してゴニョゴニョするネタを考えたい。というわけで、SQL的な自己結合。これで前後の値との比較が可能になるわけですね! 自己結合自体は普通にjoinで同じソースを置くだけ。例では、「連続して同じ値が入っている箇所」を省くため、インデックスを1つずらして結合。ただ、普通に結合すると最後の値が無いので、結合から抜け落ちてしまう。というわけで、内部結合ではなく外部結合にする。外部結合はDefaultIfEmptyを使って、MSDNに記事があるのをそのまんまな方向で。

var list = new List<int>();
list.Add(array[0]);
for (int i = 1; i < array.Length; i++)
{
	if (array[i] != array[i - 1]) list.Add(array[i]);
} 

……でも結局、こんな例ならばList使った方が遥かにスッキリなのであった。意味ないねー。とても。少しはまともな例題が考え出せやしないものなのかしらん。

Profile

Yoshifumi Kawai

Cysharp, Inc
CEO/CTO

Microsoft MVP for Developer Technologies(C#)
April 2011
|
July 2023

Twitter:@neuecc GitHub:neuecc

Archive