C# の LINQ で変換する Select

Select はシーケンスの各要素を変換するメソッドだ。射影(projection)とも呼ばれ、元のデータから必要な形に変換して新しいシーケンスを作る。

基本的な使い方

各要素に対して変換処理を適用する。

int[] numbers = { 1, 2, 3, 4, 5 };

var doubled = numbers.Select(n => n * 2);

foreach (var n in doubled)
{
    Console.WriteLine(n);  // 2, 4, 6, 8, 10
}

ラムダ式で変換ロジックを指定する。この例では各数値を2倍にしている。

型の変換

Select を使うと、要素の型を変えることもできる。

int[] numbers = { 1, 2, 3, 4, 5 };

// int から string に変換
var strings = numbers.Select(n => n.ToString());

foreach (var s in strings)
{
    Console.WriteLine(s.GetType());  // System.String
}

元のシーケンスは int だが、Select の結果は IEnumerable<string> になる。変換関数の戻り値の型が結果の型になる。

プロパティの抽出

オブジェクトのコレクションから特定のプロパティだけを取り出すのによく使う。

var people = new List&lt;Person&gt;
{
    new Person { Name = "Alice", Age = 25 },
    new Person { Name = "Bob", Age = 30 },
    new Person { Name = "Charlie", Age = 35 }
};

// 名前だけを抽出
var names = people.Select(p => p.Name);

foreach (var name in names)
{
    Console.WriteLine(name);  // Alice, Bob, Charlie
}

Person オブジェクトから Name プロパティだけを取り出している。結果は IEnumerable<string> となる。

匿名型への変換

複数のプロパティをまとめて新しい形にしたい場合は、匿名型を使う。

var people = new List&lt;Person&gt;
{
    new Person { Name = "Alice", Age = 25, City = "Tokyo" },
    new Person { Name = "Bob", Age = 30, City = "Osaka" },
    new Person { Name = "Charlie", Age = 35, City = "Tokyo" }
};

// 名前と年齢だけの匿名型に変換
var result = people.Select(p => new { p.Name, p.Age });

foreach (var item in result)
{
    Console.WriteLine($"{item.Name}: {item.Age}");
}

匿名型 new { p.Name, p.Age } を使えば、必要なプロパティだけを持つ新しいオブジェクトを作れる。不要な情報を削ぎ落とすのに便利だ。

計算結果を含める

変換時に計算を行うこともできる。

var products = new List&lt;Product&gt;
{
    new Product { Name = "Apple", Price = 100, Quantity = 5 },
    new Product { Name = "Banana", Price = 80, Quantity = 10 },
    new Product { Name = "Cherry", Price = 200, Quantity = 3 }
};

var result = products.Select(p => new 
{
    p.Name,
    Total = p.Price * p.Quantity
});

foreach (var item in result)
{
    Console.WriteLine($"{item.Name}: {item.Total}円");
}
// Apple: 500円
// Banana: 800円
// Cherry: 600円

価格と数量から合計金額を計算し、新しいプロパティとして含めている。

インデックス付きの Select

要素のインデックスを使いたい場合は、オーバーロードを使う。

string[] fruits = { "apple", "banana", "cherry" };

var result = fruits.Select((fruit, index) => $"{index + 1}. {fruit}");

foreach (var item in result)
{
    Console.WriteLine(item);
}
// 1. apple
// 2. banana
// 3. cherry

第二引数にインデックスが渡される。番号付きリストを作るときなどに便利だ。

Where と Select の組み合わせ

フィルタリングと変換を組み合わせるのは非常によくあるパターンだ。

var people = new List&lt;Person&gt;
{
    new Person { Name = "Alice", Age = 25 },
    new Person { Name = "Bob", Age = 30 },
    new Person { Name = "Charlie", Age = 35 }
};

// 30歳以上の人の名前だけを取得
var names = people
    .Where(p => p.Age >= 30)
    .Select(p => p.Name);

foreach (var name in names)
{
    Console.WriteLine(name);  // Bob, Charlie
}

まず Where で絞り込み、次に Select で必要な情報だけを取り出す。このパターンは LINQ を使う上で最も基本的な組み合わせである。