バッテラが如く

いつもお世話になっております。

【C#】Sytem.Linqで配列を特定のキーでグループ化する方法 (1次元 =>2次元に変換)

この記事の情報は次のバージョンで動作確認しています。

  • MacOS Monterey (12.1)
  • .NET Standard 2.1
  • C#

    ゲームソフトを題材にしたデータ郡があったとします。

        // ゲームソフト
        class GameSoft
        {
            public string Title;   // ゲームタイトル
            public string Company;  // 販売メーカー
        }
    
        // ゲームソフトリスト
        GameSoft[] softs = new GameSoft[]
        {
            new GameSoft(){ Title =  "バーチャファイター", Company= "セガ" },
            new GameSoft(){ Title = "ドラコンクエスト", Company= "スクエニ" },
            new GameSoft(){ Title = "バイオハザード", Company= "カプコン" },
            new GameSoft(){ Title = "マリオブラザーズ", Company= "ニンテンドウ" },
            new GameSoft(){ Title = "ファイルファンタジー", Company= "スクエニ" },
            new GameSoft(){ Title = "ゼルダの伝説", Company= "ニンテンドウ" },
            new GameSoft(){ Title =  "ぷよぷよ", Company= "セガ" },
            new GameSoft(){ Title = "ストリートファイター", Company= "カプコン" },
            new GameSoft(){ Title =  "どうぶつの森", Company= "ニンテンドウ" },
            new GameSoft(){ Title =  "SPIKE OUT", Company= "セガ" },
        };
    
    ~~
    

    これを会社(Company)単位で別々の配列にするには?といった内容です。

    キーでグループ化 (GroupdBy)

    GroupBy(x => x.キー名)でキーごとに配列を階層化できます!
    ※正確に言うとIEnumerable型になります。

    using System.Linq;
    ~~~
    
    // 会社名で仕分け
    var groups = softs.GroupBy(x => x.Company);
    
    // 各会社ごとに走査
    foreach (var group in groups)
    {
        // KeyはCompanyと同義
        Debug.Log(($"[{group.Key}]")); // 会社名をログ表示
    
        // softはGameSoftクラス
        foreach (var soft in group)
        {
            Debug.Log(($"・{soft.Title}"));  // ゲームタイトルをログ表示
        }
    }
    
    ~~~~  以下出力されたログ
    
    [セガ]
    ・バーチャファイター
    ・ぷよぷよ
    ・SPIKE OUT
    [スクエニ]
    ・ドラコンクエスト
    ・ファイルファンタジー
    [カプコン]
    ・バイオハザード
    ・ストリートファイター
    [ニンテンドウ]
    ・マリオブラザーズ
    ・ゼルダの伝説
    ・どうぶつの森
    

    このようにバラバラだった1次元配列を会社ごとの配列に仕分けるといったことができました。

    グループの並び順を変えたい場合

    ログを見ていただければ分かると思いますが、並び順は大元の配列に依存しています。

    並び順にルールを持たせたいのあれば、OrderByOrderByDescendingを使います。

    var groups = softs.GroupBy(x => x.Company);
    
    // 会社名昇順で並び替え
    foreach (var group in groups.OrderBy(x => x.Key))
    {
        Debug.Log(($"[{group.Key}]"));
    
        // ゲームタイトル昇順で並び替え
        foreach (var soft in group.OrderBy(x => x.Title))
        {
            Debug.Log(($"・{soft.Title}"));
        }
    }
    
    ~~~~  以下出力されたログ
    
    [カプコン]
    ・ストリートファイター
    ・バイオハザード
    [スクエニ]
    ・ドラコンクエスト
    ・ファイルファンタジー
    [セガ]
    ・SPIKE OUT
    ・バーチャファイター
    ・ぷよぷよ
    [ニンテンドウ]
    ・ゼルダの伝説
    ・どうぶつの森
    ・マリオブラザーズ
    

    このように「あいうえお」順に並び替えされていることが分かります。

    配列の並び替えについてはこちらの記事で詳しく解説してます。

    www.m2game.net