LINQのSelectメソッドについての説明です。
LINQってなに?という方は、[C# 入門] LINQってなに?LINQでできることを見てください。
Selectメソッドでできること
LINQのSelectメソッドを使うと、配列・コレクションの各要素から必要な項目だけを取り出すということが出来ます。また、取り出す際に要素を加工することができます。
データの集まりから必要な項目だけを取り出すことを射影というらしいです。
Selectメソッドは遅延評価になります。実際に結果が必要になった時に必要な項目を取り出す処理が実行されます。
Selectメソッドで必要な項目を取り出す
では、Selectメソッドを使ってみましょう。
下のサンプルは、SampleDataクラスのリストから必要な項目をSelectメソッドで取り出しています。
Selectメソッドは引数に必要な項目を取り出すためのメソッドを指定します。各要素に対して指定したメソッドが実行されます。
ラムダ式を使って匿名関数を渡すと簡単にSelectの引数を指定することができます。ラムダ式?という方は、[C# 入門] 匿名関数(ラムダ式)の使い道を見てください。
この取り出すためのメソッドの引数はデータソースの要素の型になります。
このサンプルの場合、SampleDataクラスが引数になります。戻り値の型は自由です。
複数の値を返す場合は匿名クラスやタプルを使うと便利です。
匿名クラスについては、[C# 入門] 匿名クラス(匿名型)の使い方を、
タプルについては、[C# 入門] タプルを使って1つの変数で複数の値を扱うを見てください。
LINQを使うには、ソースコードの先頭にusing System.Linq;を追加します。
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
public static void Main()
{
// SampleDataクラスのリストの宣言と初期化
List<SampleData> list = new List<SampleData> {
new SampleData { Data1 = 1, Data2 = 2, Data3 = 3, Data4 = 4 },
new SampleData { Data1 = 10, Data2 = 20, Data3 = 30, Data4 = 40 },
new SampleData { Data1 = 100, Data2 = 200, Data3 = 300, Data4 = 400 },
};
// Selectメソッドで必要な項目だけを取り出す
var select_list = list.Select(d => {
// 匿名クラスを使い、必要な項目+要素を使った新しい項目(Sum)を返す
return new {
Data1 = d.Data1,
Data3 = d.Data3,
Sum = d.Data1 + d.Data2 + d.Data3 + d.Data4
};
});
// 結果の表示
foreach (var data in select_list) {
Console.WriteLine($"Data1={data.Data1}, Data3={data.Data3}, Sum={data.Sum}");
}
// 必要に応じて、リストや配列に変換
var list2 = select_list.ToList(); // Listに変換
var ary = select_list.ToArray(); // 配列に変換
}
}
class SampleData
{
public int Data1 { get; set; }
public int Data2 { get; set; }
public int Data3 { get; set; }
public int Data4 { get; set; }
}
実行結果はこんな感じです。
Data1=1, Data3=3, Sum=10
Data1=10, Data3=30, Sum=100
Data1=100, Data3=300, Sum=1000
Selectメソッドの戻り値はIEnumerable<T>型のコレクションになります。Tの部分はSelectメソッドに指定した項目を取り出すメソッドの戻り値の型になります。
サンプルコードの場合はIEnumerable<匿名クラス>です。
IEnumerableなのでforeachのinに指定することができます。
必要に応じて、ToListメソッドを使いListに変換したり、ToArrayメソッドを使い配列に変換することができます。
var list2 = select_list.ToList(); // Listに変換
var ary = select_list.ToArray(); // 配列に変換
要素のインデックスも同時に取り出す
Selectメソッドにはもうひとつ、要素のインデックスが取得できるオーバーロードがあります。
こちらもSelectメソッドの引数に必要な項目を取り出すメソッドを指定しますが、取り出すメソッドの引数は各要素のデータ型と要素のインデックス(int型)になります。戻り値の型は自由です。
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
public static void Main()
{
// SampleDataクラスのリストの宣言と初期化
List<SampleData> list = new List<SampleData> {
new SampleData { Data1 = 1, Data2 = 2, Data3 = 3, Data4 = 4 },
new SampleData { Data1 = 10, Data2 = 20, Data3 = 30, Data4 = 40 },
new SampleData { Data1 = 100, Data2 = 200, Data3 = 300, Data4 = 400 },
};
// Selectメソッドで必要な項目だけを取り出す
// ラムダ式の引数パラメータ d はSampleData型、i はint型(要素のインデックス)になる
var select_list = list.Select((d, i) => {
// 匿名クラスを使い、必要な項目+要素を使った新しい項目(Sum)を返す
return new {
index = i,
Data1 = d.Data1,
Data3 = d.Data3,
Sum = d.Data1 + d.Data2 + d.Data3 + d.Data4
};
});
// 結果の表示
foreach (var data in select_list) {
Console.WriteLine($"Index={data.index}, Data1={data.Data1}, Data3={data.Data3}, Sum={data.Sum}");
}
}
}
class SampleData
{
public int Data1 { get; set; }
public int Data2 { get; set; }
public int Data3 { get; set; }
public int Data4 { get; set; }
}
Index=0, Data1=1, Data3=3, Sum=10
Index=1, Data1=10, Data3=30, Sum=100
Index=2, Data1=100, Data3=300, Sum=1000
16行目 (d, i) => { の i が要素のインデックスです。
C# 記事まとめページに戻る(他のサンプルコードもこちら)
コメント