sh1’s diary

プログラミング、読んだ本、資格試験、ゲームとか私を記録するところ

配列(コレクション)データを条件にあったデータのみを抽出する tips

配列の操作例

Linq を使って配列(コレクション)のデータを、別の形の配列に変換するサンプルです。

配列やコレクションから必要なデータを抽出して、期待する形式のコレクション等に変換することを想定した tips です。

f:id:shikaku_sh:20200605102205p:plain:w500
テストコードを書こう

こういった短いコードを書くときは、テストコードを sharplab.io で書くと楽だったりすると思います。

配列のデータにインデックスを追加する

まず、最初に配列に1から始まるインデックスを追加するサンプル。匿名型を使うことでシンプルに利用できるようになりました。この形から少しずつデータの形を変えていきたいと思います。

var sources = new int[] { 1,2,3,4,1,2,3,4,1,4,2,4 };

var indexed = sources.Select((val, index) => new { val, index });
        
    
foreach (var source in indexed)
{
    Console.WriteLine(source);
}
{ val = 1, index = 0 }
{ val = 2, index = 1 }
{ val = 3, index = 2 }
{ val = 4, index = 3 }
{ val = 1, index = 4 }
{ val = 2, index = 5 }
{ val = 3, index = 6 }
{ val = 4, index = 7 }
{ val = 1, index = 8 }
{ val = 4, index = 9 }
{ val = 2, index = 10 }
{ val = 4, index = 11 }


条件に合ったデータだけを取得する

3より大きい数字のデータを取得します。このとき、インデックスを工夫してグルーピングしやすい groupNo を持たせてみました。

var sources = new int[] { 1,2,3,4,1,2,3,4,1,4,2,4 };
var samples = sources.Select((val, index) => new { val, index })
                     .Where(p => p.val >= 3)
                     .Select((val, groupNo) => new { val.val, groupNo = val.index - groupNo });

foreach (var source in samples)
{
    Console.WriteLine(source);
}
{ val = 3, groupNo = 2 }
{ val = 4, groupNo = 2 }
{ val = 3, groupNo = 4 }
{ val = 4, groupNo = 4 }
{ val = 4, groupNo = 5 }
{ val = 4, groupNo = 6 }


条件にあったデータをグルーピングする

前の条件で用意しておいた groupNo で、二次元配列の形に変換しました。いわゆるジャンケンの連勝数を数えるような条件です。

意外とこの形に変換できると便利だったりするのでメモ。

var sources = new int[] { 1,2,3,4,1,2,3,4,1,4,2,4 };
var samples = sources.Select((val, index) => new { val, index })
                     .Where(p => p.val >= 3)
                     .Select((val, groupNo) => new { val.val, groupNo = val.index - groupNo })
                     .GroupBy(p => p.groupNo, p => p.val);

foreach (var groupData in samples)
{
    foreach (var source in groupData)
    {
        Console.WriteLine(source);
    }
    
    Console.WriteLine("--");
}
3
4
--
3
4
--
4
--
4
--


二次元配列を一次元配列に変換する(元に戻す)

Enumerable.SelectMany メソッドを利用することで、コレクションを1つのシーケンスの平坦な状態に戻すことができます。

var samples = sources.Select((val, index) => new { val, index })
                     .Where(p => p.val >= 3)
                     .Select((val, groupNo) => new { val.val, groupNo = val.index - groupNo })
                     .GroupBy(p => p.groupNo, p => p.val);

var array = samples.SelectMany(p => p).ToArray();

foreach (var data in array)
{
    Console.WriteLine(data);
}
3
4
3
4
4
4

参考