【C#】LINQ の Select を使用する方法

C#が根強い人気誇る一つの要因として挙げられるのが LINQ です。LINQ を使いこなすことができれば、C# はかなり使いやすい言語です。その中でも前回の「」に引き続いて重要なのが Select メソッドです。

この記事では Select メソッドについて解説していきます。Whereメソッドに引き続いて学んでおくべきは「Selectメソッド」になるので、LINQの基礎としてぜひとも押さえておきましょう。

Selectメソッドの基礎知識

まずはSelectメソッドの基礎知識から紹介していきます。SelectメソッドはMicrosoftの公式ホームページでは以下のように記述されているメソッドになります。

要素のインデックスを組み込むことにより、シーケンスの各要素を新しいフォームに射影します。

重要な部分は「新しいフォームに射影します。」の部分ですね。要するにSelectメソッドの括弧内に渡されたFuncの内容で新しいコレクションを作成するという意味になります。

また、Selectメソッドで作成されたコレクションは遅延実行により実装されるため、別インスタンスで使用したい場合はToArrayやToListメソッドを使用する必要があることに注意しましょう。

Selectメソッドを書く方法

では早速Selectメソッドを実際に書いていきたいと思います。新規のコンソールアプリケーションを作成して、以下のアプリケーションを作成してみてください。

using System;
using System.Linq;

namespace App01
{
    class Program
    {
        static void Main(string[] args)
        {
            var numList = Enumerable.Range(1, 10);

            //Selectメソッドを使用する
            var newList = numList.Select(x => x * x);

            foreach(var item in newList)
            {
                //コンソール画面に出力する
                Console.WriteLine(item.ToString());
            }
            Console.ReadLine();
        }
    }
}

上記のアプリケーションでは以下のように出力されているはずです。

1
4
9
16
25
36
49
64
81
100

Selectメソッドの括弧内のラムダ式に注目してみてください。ラムダ式は以下のようになっており、Funcの形式となっています。型推論により戻り値はint型となります。

var newList = numList.Select(x => x * x);

引数である「x」は「numList」の各要素ですのでint型となります。「=> x * x」の部分は「xとxを掛け算して、その計算結果を戻り値とする」ため、int型 * int型 = int型となります。このFuncは引数がint型で戻り値もint型になるということです。

処理内容が「x * xを戻り値とする」ため、新規で射影されるコレクションは各要素の二乗を格納する内容となります。そのため「1, 4, 9, 16, 25…」となっているのです。Selectが新しいコレクションを作るという意味がよく分かりますね。

SelectManyメソッドを書く方法

Selectと別バージョンとして「SelectManyメソッド」というものがあります。これもよく使うメソッドなので当記事で触れておきたいと思います。このメソッドは公式では以下のように記述されています。

シーケンスの各要素を IEnumerable に射影し、結果のシーケンスを 1 つのシーケンスに平坦化します。

「平坦化」という聞きなれないワードがあるかと思います。「平坦化」とはコレクション内に格納されたコレクションのプロパティを抜き取って、別のコレクションにするという意味になります。以下、サンプルを使用して紹介します。

using System;
using System.Collections.Generic;
using System.Linq;

namespace App02
{
    class Program
    {
        public class Menu
        {
            public List<int> Prices { get; set; }
            public string Name { get; set; }
        }

        static void Main(string[] args)
        {
            var menues = new List<Menu>()
            {
                new Menu(){ Name="唐揚げ", Prices=new List<int>(){ 250, 300, 450 }, },
                new Menu(){ Name="たこ焼き", Prices=new List<int>(){ 320, 380, 400 }, },
                new Menu(){ Name="イカ焼き", Prices=new List<int>(){ 280, 320, 480 }, },
            };

            //シーケンスからPricesプロパティだけ取得して平坦化する
            var newList = menues.SelectMany(x => x.Prices);
            foreach(var item in newList)
            {
                Console.WriteLine(item);
            }
            Console.ReadLine();
        }
    }
}

各Menuクラスの要素からPricesというコレクションのプロパティを抜き取って一つのコレクションに平坦化した例です。出力結果は以下のようになります。各要素を重複なく宣言したのでどの要素から取得したのか分かると思います。

250
300
450
320
380
400
280
320
480

SelectManyメソッドはコレクションの各要素に含まれるコレクションを平坦化する処理ですが、これも使う場面がありそうでしたので紹介しておきました。データ構造がコレクションのネスト構造であれば、SelectManyメソッドを使用してデータを一回で取得できるので活用してみてください。

以上、ここではSelectメソッドとSelectManyメソッドを解説しました。Selectメソッドは別のコレクションに射影する処理をしてくれます。特定の処理を付与して別のコレクションを作成することができる機能なので覚えておきましょう。