for WPF developers
Home Profile Tips 全記事一覧

Select 拡張メソッドでシーケンスの各要素を別の型に射影する

(2017/03/14 10:37:44 created.)

Select 拡張メソッドはシーケンスの各要素を元に、別の型のシーケンスを生成します。

Program.cs
  1. namespace Tips_Linq
  2. {
  3.     using System;
  4.     using System.Linq;
  5.  
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {
  10.             var numbers = Enumerable.Range(7, 10);
  11.             foreach (var number in numbers)
  12.             {
  13.                 Console.WriteLine(number);
  14.             }
  15.  
  16.             Console.WriteLine("Select 拡張メソッドで射影します。");
  17.             var strings = numbers.Select(x => "0x" + x.ToString("X4"));
  18.             foreach (var str in strings)
  19.             {
  20.                 Console.WriteLine(str);
  21.             }
  22.  
  23.             Console.ReadKey();
  24.         }
  25.     }
  26. }


上記の例では、Range 拡張メソッドによって生成した int 型のシーケンスを、Select 拡張メソッドによって string 型のシーケンスに射影しています。Select 拡張メソッドの引数に各要素を用いた処理を記述し、その処理から得られる結果が新たに生成されるシーケンスの各要素となります。上記のコードでは、int 型の各要素を使用して ToString() メソッドを使用しています。その処理の結果が string 型となっているため、生成される新たなシーケンスは string 型のシーケンスとなっています。

Select 拡張メソッドにはもうひとつオーバーロードがあり、こちらを使用することで現在処理中の要素が元のシーケンスの何番目であるかを知ることができます。次のコード例を見てみましょう。

Program.cs
  1. namespace Tips_Linq
  2. {
  3.     using System;
  4.     using System.Linq;
  5.  
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {
  10.             var numbers = Enumerable.Range(7, 10);
  11.             foreach (var number in numbers)
  12.             {
  13.                 Console.WriteLine(number);
  14.             }
  15.  
  16.             Console.WriteLine("要素のインデックスを使用することもできます。");
  17.             var indexes = numbers.Select((x, i) => i);
  18.             foreach (var index in indexes)
  19.             {
  20.                 Console.WriteLine(index);
  21.             }
  22.  
  23.             Console.ReadKey();
  24.         }
  25.     }
  26. }


入力引数として指定するデリゲートに、入力引数を 2 つ持つデリゲートを指定することで、その 2 番目の引数が要素のインデックスとなります。上記のコード例ではそのインデックスそのものを新たなシーケンスの要素としているため、0 を先頭としてインクリメントされている様子がわかります。

この機能を利用することで、foreach 文を使いながらも要素のインデックスを用いた処理を書くことができます。

Program.cs
  1. namespace Tips_Linq
  2. {
  3.     using System;
  4.     using System.Linq;
  5.  
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {
  10.             var numbers = Enumerable.Range(7, 10);
  11.             foreach (var number in numbers)
  12.             {
  13.                 Console.WriteLine(number);
  14.             }
  15.  
  16.             Console.WriteLine("foreach でインデックスを使いたいときに便利です。");
  17.             foreach (var obj in numbers.Select((x, i) => new { number = x, index = i }))
  18.             {
  19.                 Console.WriteLine(obj.index + " 番目の要素は " + obj.number + " です。");
  20.             }
  21.  
  22.             Console.ReadKey();
  23.         }
  24.     }
  25. }