C# PR

【C#】LINQのConcatで配列・リスト結合を簡単に!

【C#】LINQのConcatで配列・リスト結合を簡単に!
記事内に商品プロモーションを含む場合があります

こんにちは!

プログラミングをしていると、複数のコレクションを1つにまとめたいと思うことがありますよね。

複数のリストを結合する良い方法はないかな…
配列の結合って、いちいちループを書くしかないの?
C#でコレクションの結合を効率的に行う方法が知りたい

もしかすると、そんな疑問を持っているかもしれませんね。

この記事では、C#のLINQが提供する強力なメソッド「Concat」について、基本的な使い方から実践的な活用方法、そして注意点やパフォーマンスについて詳しく解説していきます。

この記事は、以下のような方におすすめです。

この記事はこんな人におすすめ!
  • C#のLINQ Concatメソッドの基本を理解したい方
  • 複数のコレクション(配列やリスト)を効率的に結合したい方
  • Concatと似たメソッドの違いを知りたい方
  • Concatメソッドのパフォーマンスや注意点について学びたい方

この記事を読めば、Concatメソッドの使い方をマスターできるだけでなく、いつ使うべきか、いつ別の方法を選ぶべきかも判断できるようになります。さらに、よくある間違いを避け、効率的にコレクションを操作するテクニックも身につけられます。

「C#でコレクションを効率的に結合したい!」「LINQのConcatメソッドをもっと活用したい!」と少しでも考えているあなたは、ぜひ最後まで読んでください。

それでは、順を追って詳しく見ていきましょう!

C#のLINQとは?

まずは、LINQについて簡単におさらいしましょう。

LINQ(Language Integrated Query)は、C#に統合されたクエリ機能で、コレクションに対する様々な操作を簡潔に書けるようにしたものです。データベースのSQL文のように、コレクションからデータを取得したり、フィルタリングしたり、変換したりすることができます。

LINQは、.NET Framework 3.5から導入され、C#プログラミングの効率を大きく向上させました。配列やリスト、辞書などの様々なコレクションに対して同じ構文でアクセスできるのが大きな特徴です。

LINQを使うには、以下の名前空間をインポートする必要があります。

using System.Linq;

LINQを使うことで、複雑なループ処理やフィルタリングを簡潔に記述できるようになります。例えば、配列から特定の条件の要素を抽出する処理は、通常のループを使うと以下のようになります。

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
List<int> evenNumbers = new List<int>();

foreach (int number in numbers)
{
  if (number % 2 == 0)
  {
    evenNumbers.Add(number);
  }
}

一方、LINQを使うと、次のように書くことができます。

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(n => n % 2 == 0);

このように、LINQを使うことで、コードの可読性と保守性が向上します。そして、このLINQの中でもコレクションの結合に使われるのが「Concat」メソッドなのです。

Concatメソッドとは?

Concatメソッドは、2つのシーケンス(配列やリストなどのコレクション)を1つのシーケンスに結合するためのLINQメソッドです。

単純に言えば、2つの配列やリストを「つなげる」ための便利な方法を提供してくれるのです。

Concatメソッドの基本構文

Concatメソッドは次のような構文で使用します。

IEnumerable<T> result = firstSequence.Concat(secondSequence);

ここで、firstSequencesecondSequenceは同じ型Tの要素を持つコレクションです。結果もIEnumerable<T>型で返されます。

簡単な例

整数の配列を2つ結合する簡単な例を見てみましょう。

int[] numbers1 = { 1, 2, 3 };
int[] numbers2 = { 4, 5, 6 };

var combinedNumbers = numbers1.Concat(numbers2);

// 結果: 1, 2, 3, 4, 5, 6
foreach (var number in combinedNumbers)
{
  Console.WriteLine(number);
}

この例では、numbers1numbers2という2つの配列をConcatメソッドで結合しています。結果は、両方の配列の要素を順番に含む新しいシーケンスになります。

Concatメソッドの特徴

Concatメソッドには、いくつかの重要な特徴があります。

  • 元のコレクションは変更されません。新しいシーケンスが生成されます。
  • 結果は即時に計算されず、要素が必要になった時点で評価されます(これをLINQの「遅延実行」といいます)。
  • 結合する2つのコレクションは同じ型の要素を持つ必要があります。

これらの特徴を理解しておくことで、Concatメソッドを効果的に活用することができます。

Concatメソッドの使い方

ここからは、Concatメソッドの具体的な使い方と様々な場面での活用法を見ていきましょう。

基本的な使用例

先ほどの整数配列の例に加えて、文字列のリストや複雑なオブジェクトのコレクションでも使えます。

文字列リストの結合

List<string> fruits1 = new List<string> { "りんご", "バナナ", "みかん" };
List<string> fruits2 = new List<string> { "いちご", "ぶどう", "メロン" };

var allFruits = fruits1.Concat(fruits2);

// 結果: りんご, バナナ, みかん, いちご, ぶどう, メロン
foreach (var fruit in allFruits)
{
  Console.WriteLine(fruit);
}

オブジェクトのコレクション結合

クラスのインスタンスのコレクションも結合できます。

public class Product
{
  public string Name { get; set; }
  public decimal Price { get; set; }
}

List<Product> products1 = new List<Product>
{
  new Product { Name = "ノートPC", Price = 80000 },
  new Product { Name = "マウス", Price = 3000 }
};

List<Product> products2 = new List<Product>
{
  new Product { Name = "キーボード", Price = 5000 },
  new Product { Name = "モニター", Price = 25000 }
};

var allProducts = products1.Concat(products2);

foreach (var product in allProducts)
{
  Console.WriteLine($"{product.Name}: {product.Price}円");
}

複数のコレクションの結合

2つ以上のコレクションを結合したい場合は、Concatメソッドを連続して呼び出すことができます。

int[] numbers1 = { 1, 2, 3 };
int[] numbers2 = { 4, 5, 6 };
int[] numbers3 = { 7, 8, 9 };

var combinedNumbers = numbers1.Concat(numbers2).Concat(numbers3);

// 結果: 1, 2, 3, 4, 5, 6, 7, 8, 9
foreach (var number in combinedNumbers)
{
  Console.WriteLine(number);
}

異なる型のコレクションの結合

異なる型のコレクションを結合するには、共通の基底クラスやインターフェースを使用するか、匿名型やタプルに変換する必要があります。

共通の基底クラスを使った例

public class Animal
{
  public string Name { get; set; }
}

public class Dog : Animal
{
  public string Breed { get; set; }
}

public class Cat : Animal
{
  public bool IsIndoor { get; set; }
}

List<Dog> dogs = new List<Dog>
{
  new Dog { Name = "ポチ", Breed = "柴犬" },
  new Dog { Name = "ハチ", Breed = "ゴールデンレトリバー" }
};

List<Cat> cats = new List<Cat>
{
  new Cat { Name = "タマ", IsIndoor = true },
  new Cat { Name = "ミケ", IsIndoor = false }
};

// Animal型として結合する
IEnumerable<Animal> pets = dogs.Cast<Animal>().Concat(cats.Cast<Animal>());

foreach (var pet in pets)
{
  Console.WriteLine(pet.Name);
}

結果の操作

Concatで結合した後、さらに他のLINQメソッドを使って結果を加工することができます。

int[] numbers1 = { 1, 3, 5 };
int[] numbers2 = { 2, 4, 6 };

var combinedNumbers = numbers1.Concat(numbers2);

// 結合後に並べ替え
var sortedNumbers = combinedNumbers.OrderBy(n => n);
// 結果: 1, 2, 3, 4, 5, 6

// 結合後にフィルタリング
var filteredNumbers = combinedNumbers.Where(n => n > 3);
// 結果: 4, 5, 6

// 結合後に集計
var sum = combinedNumbers.Sum();
// 結果: 21

この例では、結合した後に並べ替え、フィルタリング、集計といった操作を行っています。LINQのメソッドチェーンを活用することで、複雑なデータ操作も簡潔に記述できます。

Concatと似たメソッドの違い

C#には、Concatと似た機能を持つ他のメソッドもあります。ここでは、それらの違いを解説し、どんな場面で使い分けるべきかを見ていきましょう。

Concat vs Union

Unionメソッドは、2つのコレクションの「和集合」を返します。つまり、重複要素を排除した結果を得ることができます。

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

var concatResult = numbers1.Concat(numbers2);
// 結果: 1, 2, 3, 3, 4, 5(重複あり)

var unionResult = numbers1.Union(numbers2);
// 結果: 1, 2, 3, 4, 5(重複なし)
メソッド 動作 重複の扱い 使いどき
Concat 2つのコレクションを単純に結合 重複を保持する 順番を維持したままコレクションを結合したいとき
Union 和集合を求める 重複を排除する 重複のない結合結果が欲しいとき

Concat vs Enumerable.Append/Prepend

AppendPrependは、単一の要素をコレクションの末尾または先頭に追加します。

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

var appendResult = numbers.Append(4);
// 結果: 1, 2, 3, 4

var prependResult = numbers.Prepend(0);
// 結果: 0, 1, 2, 3

複数の要素を追加する場合は、Concatの方が適しています。

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

// 複数要素を末尾に追加
var result = numbers.Concat(moreNumbers);
// 結果: 1, 2, 3, 4, 5, 6

Concat vs List.AddRange

List<T>クラスのAddRangeメソッドも、リストに別のコレクションの要素を追加します。しかし、大きな違いがあります。

List<int> numbers = new List<int> { 1, 2, 3 };
int[] moreNumbers = { 4, 5, 6 };

// AddRangeの場合
numbers.AddRange(moreNumbers);
// 結果: numbers = [1, 2, 3, 4, 5, 6](元のリストが変更される)

// Concatの場合
List<int> numbers2 = new List<int> { 1, 2, 3 };
var result = numbers2.Concat(moreNumbers);
// numbers2は変更されず、resultに新しいシーケンスが格納される
メソッド 元のコレクション 返り値 使いどき
Concat 変更しない 新しいIEnumerable 元のコレクションを保持したいとき
AddRange 変更する なし(void) リストを直接更新したいとき

Concat vs SelectMany

SelectManyは、入れ子になったコレクションを平坦化(フラット化)するためのメソッドです。

List<List<int>> nestedLists = new List<List<int>>
{
  new List<int> { 1, 2 },
  new List<int> { 3, 4 },
  new List<int> { 5, 6 }
};

// SelectManyを使った平坦化
var flattened = nestedLists.SelectMany(list => list);
// 結果: 1, 2, 3, 4, 5, 6

複数のコレクションを1つの変数にまとめて結合する場合は、SelectManyが効果的です。

int[] numbers1 = { 1, 2 };
int[] numbers2 = { 3, 4 };
int[] numbers3 = { 5, 6 };

var collections = new[] { numbers1, numbers2, numbers3 };
var allNumbers = collections.SelectMany(array => array);
// 結果: 1, 2, 3, 4, 5, 6

Concatメソッドの注意点とパフォーマンス

Concatメソッドを使う際には、いくつかの注意点やパフォーマンス上の考慮事項があります。

遅延評価の仕組み

Concatメソッドは、LINQの他のメソッドと同様に「遅延評価」されます。つまり、結果のシーケンスを実際に使うまで、具体的な結合操作は行われません。

int[] numbers1 = { 1, 2, 3 };
int[] numbers2 = { 4, 5, 6 };

// この時点では結合は実行されない
var combinedNumbers = numbers1.Concat(numbers2);

// ここで初めて結合が実行される
foreach (var number in combinedNumbers)
{
  Console.WriteLine(number);
}

この特性により、大きなコレクションを扱う場合でもメモリ効率が良くなります。ただし、結果を何度も繰り返し使用する場合は、ToList()ToArray()メソッドを使って結果を具体化しておくとパフォーマンスが向上することがあります。

// 結果を具体化する
var combinedList = numbers1.Concat(numbers2).ToList();

複数回の結合とパフォーマンス

多数のコレクションを結合する場合、次のように連続してConcatを呼び出すことができます。

var result = collection1.Concat(collection2).Concat(collection3).Concat(collection4);

しかし、コレクションの数が多い場合、このアプローチはパフォーマンスの問題を引き起こす可能性があります。その場合は、以下のようにSelectManyを使用する方が効率的です。

var collections = new[] { collection1, collection2, collection3, collection4 };
var result = collections.SelectMany(c => c);

メモリ使用量と大きなコレクション

Concatメソッド自体は遅延評価されるため、メモリ効率が良いのですが、結果をToList()ToArray()で具体化する場合は、結合されるコレクションの全ての要素分のメモリが必要になります。

非常に大きなコレクションを扱う場合は、結果を具体化せず、必要な部分だけを処理するようにしたほうがメモリ効率が良いことがあります。

// 大きなコレクションの結合
var hugeResult = hugeCollection1.Concat(hugeCollection2);

// 最初の10要素だけを処理する例
foreach (var item in hugeResult.Take(10))
{
  ProcessItem(item);
}

並列処理との併用

パフォーマンスを向上させたい場合、ParallelLINQとの併用も検討できます。ただし、順序が重要な場合は注意が必要です。

using System.Threading.Tasks;

var result = collection1.Concat(collection2).AsParallel().Where(item => SomeComplexCondition(item));

キャリア形成/給与還元
ひとつひとつ真摯に向き合う企業
ONE_WEDGE社員募集

株式会社 ONE WEDGEでは、新たな仲間を募集しています!

私たちと一緒に、革新的で充実したキャリアを築きませんか?
当社は、従業員が仕事と私生活のバランスを大切にできるよう、充実した福利厚生を整えています。

  • 完全週休2日制(土日休み)で、祝日や夏季休暇、年末年始休暇もしっかり保証!
  • 様々な休暇制度(有給、慶弔、産前・産後、育児、バースデー休暇、有給6日取得で特別休暇付与)を完備!
  • 従業員の成長と健康を支援するための表彰制度、資格取得支援、健康促進手当など!
  • 生活を支えるテレワーク手当、記事寄稿手当、結婚祝金・出産祝金など、様々な手当を提供!
  • 自己啓発としての書籍購入制度や、メンバー間のコミュニケーションを深める交流費補助!
  • 成果に応じた決算賞与や、リファラル採用手当、AI手当など、頑張りをしっかり評価!
  • ワークライフバランスを重視し、副業もOK!

株式会社 ONE WEDGEでは、一人ひとりの従業員が自己実現できる環境を大切にしています。
共に成長し、刺激を与え合える仲間をお待ちしております。
あなたの能力と熱意を、ぜひ当社で発揮してください。
ご応募お待ちしております!

ホームページ、採用情報は下記ボタンからご確認ください!

応募、ご質問など、LINEでお気軽にご相談ください♪

まとめ

ここまで、C#のLINQにおけるConcatメソッドについて詳しく解説してきました。改めて、重要なポイントをおさらいしましょう。

  • Concatメソッドは、2つのシーケンス(配列、リストなど)を結合するためのLINQメソッド
  • 元のコレクションを変更せず、新しいシーケンスを生成する非破壊的操作
  • 遅延評価により、必要になるまで実際の結合処理は行われない
  • Unionとの主な違いは、Concatは重複要素を保持するのに対し、Unionは排除する点
  • 大量のコレクションを結合する場合は、連続したConcatよりもSelectManyを使う方が効率的な場合がある
  • パフォーマンスを考慮する場合は、遅延評価の特性を活かすか、ToList()などで結果を具体化するか適切に選択する

Concatメソッドは、C#でコレクションを操作する際の強力なツールです。適切な場面で使用することで、コードの可読性を高め、効率的なプログラミングが可能になります。

この記事で解説した基本から応用までの知識を活かして、あなたのC#プログラミングをさらに洗練させてください。コレクションの操作が簡潔に、そして効率的に行えるようになることでしょう。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です