LINQ

[C#/LINQ] Concatメソッドの使い方 – 複数のコレクションを結合する

C#のLINQにおけるConcatメソッドは、2つのコレクションを結合して1つのシーケンスを作成するために使用されます。

Concatは、元のコレクションを変更せず、新しいシーケンスを返します。

例えば、IEnumerable<T>型のコレクション同士を結合する際に使います。

Concatは、最初のコレクションの要素を先に、次に2番目のコレクションの要素を順番に列挙します。

重複する要素はそのまま保持され、フィルタリングは行われません。

Concatメソッドとは

Concatメソッドは、C#のLINQ(Language Integrated Query)において、複数のコレクションを結合するための便利なメソッドです。

このメソッドを使用することで、配列やリストなどのコレクションを簡単に連結し、新しいコレクションを生成することができます。

Concatメソッドは、元のコレクションの要素をそのまま保持し、結合した結果を返します。

Concatメソッドは、特にデータの集約や表示の際に役立ちます。

例えば、異なるデータソースから取得した情報を一つのリストにまとめたい場合や、複数のフィルタリング結果を一つのコレクションに統合したい場合に利用されます。

LINQの他のメソッドと組み合わせることで、より複雑なデータ操作も可能になります。

Concatメソッドの基本的な使用例

配列同士を結合する例

配列同士を結合する際には、Concatメソッドを使用することで簡単に新しい配列を作成できます。

以下のサンプルコードでは、2つの整数配列を結合しています。

using System;
using System.Linq;
class Program
{
    static void Main()
    {
        int[] array1 = { 1, 2, 3 };
        int[] array2 = { 4, 5, 6 };
        var result = array1.Concat(array2);
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}
1
2
3
4
5
6

リスト同士を結合する例

リスト同士を結合する場合も、Concatメソッドを利用できます。

以下のサンプルコードでは、2つの文字列リストを結合しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<string> list1 = new List<string> { "A", "B", "C" };
        List<string> list2 = new List<string> { "D", "E", "F" };
        var result = list1.Concat(list2);
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}
A
B
C
D
E
F

IEnumerable<T>を使った結合例

IEnumerable<T>を使用して、より柔軟にコレクションを結合することも可能です。

以下のサンプルコードでは、IEnumerableを使って2つの異なるコレクションを結合しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        IEnumerable<int> numbers1 = new List<int> { 1, 2, 3 };
        IEnumerable<int> numbers2 = new List<int> { 4, 5, 6 };
        var result = numbers1.Concat(numbers2);
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}
1
2
3
4
5
6

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

異なる型のコレクションを結合する場合、型を統一する必要があります。

以下のサンプルコードでは、整数と文字列を結合するために、object型のコレクションを使用しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        IEnumerable<object> mixed1 = new List<object> { 1, "A", 2 };
        IEnumerable<object> mixed2 = new List<object> { "B", 3, "C" };
        var result = mixed1.Concat(mixed2);
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}
1
A
2
B
3
C

Concatメソッドの動作の詳細

順序の保持について

Concatメソッドは、結合するコレクションの要素の順序を保持します。

最初のコレクションの要素が先に、次に結合するコレクションの要素が続きます。

これにより、データの整合性が保たれ、期待通りの順序で結果を得ることができます。

以下のサンプルコードでは、順序が保持されていることを示しています。

using System;
using System.Linq;
class Program
{
    static void Main()
    {
        int[] array1 = { 1, 2, 3 };
        int[] array2 = { 4, 5, 6 };
        var result = array1.Concat(array2);
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}
1
2
3
4
5
6

重複要素の扱い

Concatメソッドは、重複要素をそのまま保持します。

つまり、結合するコレクションに同じ要素が存在する場合、それらは結果に含まれます。

重複を除外したい場合は、別途Distinctメソッドを使用する必要があります。

以下のサンプルコードでは、重複要素が保持されていることを示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<int> list1 = new List<int> { 1, 2, 3, 3 };
        List<int> list2 = new List<int> { 3, 4, 5 };
        var result = list1.Concat(list2);
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}
1
2
3
3
3
4
5

Null値を含むコレクションの結合

Concatメソッドは、Null値を含むコレクションを結合することができます。

Null値はそのまま結果に含まれ、他の要素と同様に扱われます。

以下のサンプルコードでは、Null値を含むコレクションの結合を示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<string> list1 = new List<string> { "A", null, "C" };
        List<string> list2 = new List<string> { "D", "E", null };
        var result = list1.Concat(list2);
        foreach (var item in result)
        {
            Console.WriteLine(item ?? "null");
        }
    }
}
A
null
C
D
E
null

Concatメソッドの戻り値の型

Concatメソッドの戻り値は、IEnumerable<T>型です。

これにより、結合した結果をさらにLINQメソッドで操作することが可能です。

戻り値の型がIEnumerableであるため、遅延実行が行われ、必要なときに要素が生成されます。

以下のサンプルコードでは、Concatメソッドの戻り値を利用して、さらにフィルタリングを行っています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<int> list1 = new List<int> { 1, 2, 3 };
        List<int> list2 = new List<int> { 4, 5, 6 };
        var result = list1.Concat(list2)
                          .Where(x => x > 3); // 3より大きい要素をフィルタリング
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}
4
5
6

Concatメソッドの応用例

複数のコレクションを動的に結合する

複数のコレクションを動的に結合する場合、Concatメソッドを使用することで、ユーザーの入力や条件に応じてコレクションを組み合わせることができます。

以下のサンプルコードでは、ユーザーが選択したコレクションを結合しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<int> collection1 = new List<int> { 1, 2, 3 };
        List<int> collection2 = new List<int> { 4, 5, 6 };
        List<int> collection3 = new List<int> { 7, 8, 9 };
        Console.WriteLine("結合するコレクションを選択してください (1, 2, 3):");
        var choice = Console.ReadLine();
        IEnumerable<int> result = collection1;
        if (choice == "2")
        {
            result = result.Concat(collection2);
        }
        else if (choice == "3")
        {
            result = result.Concat(collection3);
        }
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}

出力結果(選択肢に応じて変わります):

1
2
3

または

1
2
3
4
5
6

または

1
2
3
7
8
9

データベースから取得したデータの結合

データベースから取得したデータを結合する際にも、Concatメソッドは非常に便利です。

以下のサンプルコードでは、2つの異なるデータベーステーブルから取得したデータを結合しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        // サンプルデータ
        List<string> table1 = new List<string> { "Alice", "Bob" };
        List<string> table2 = new List<string> { "Charlie", "David" };
        var result = table1.Concat(table2);
        foreach (var name in result)
        {
            Console.WriteLine(name);
        }
    }
}
Alice
Bob
Charlie
David

複数のフィルタリング結果を結合する

複数のフィルタリング結果を結合することで、特定の条件に合致するデータを一つのコレクションにまとめることができます。

以下のサンプルコードでは、異なる条件でフィルタリングした結果を結合しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
        var evenNumbers = numbers.Where(x => x % 2 == 0);
        var greaterThanThree = numbers.Where(x => x > 3);
        var result = evenNumbers.Concat(greaterThanThree);
        foreach (var number in result)
        {
            Console.WriteLine(number);
        }
    }
}
2
4
6
4
5
6

複数のファイルから読み込んだデータを結合する

複数のファイルからデータを読み込み、それを結合することも可能です。

以下のサンプルコードでは、2つのテキストファイルからデータを読み込み、Concatメソッドで結合しています。

using System;
using System.IO;
using System.Linq;
class Program
{
    static void Main()
    {
        // ファイルからデータを読み込む
        var file1Lines = File.ReadAllLines("file1.txt");
        var file2Lines = File.ReadAllLines("file2.txt");
        var result = file1Lines.Concat(file2Lines);
        foreach (var line in result)
        {
            Console.WriteLine(line);
        }
    }
}

出力結果(ファイルの内容に依存):

ファイル1の内容1
ファイル1の内容2
ファイル2の内容1
ファイル2の内容2

このように、Concatメソッドを使用することで、さまざまなデータソースからの情報を簡単に結合することができます。

Concatメソッドと他の結合メソッドの比較

Unionメソッドとの違い

Unionメソッドは、2つのコレクションを結合する際に、重複する要素を自動的に除外します。

一方、Concatメソッドは重複をそのまま保持します。

以下のサンプルコードでは、UnionメソッドConcatメソッドの違いを示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<int> list1 = new List<int> { 1, 2, 3, 3 };
        List<int> list2 = new List<int> { 3, 4, 5 };
        var unionResult = list1.Union(list2);
        var concatResult = list1.Concat(list2);
        Console.WriteLine("Unionの結果:");
        foreach (var item in unionResult)
        {
            Console.WriteLine(item);
        }
        Console.WriteLine("Concatの結果:");
        foreach (var item in concatResult)
        {
            Console.WriteLine(item);
        }
    }
}
Unionの結果:
1
2
3
4
5
Concatの結果:
1
2
3
3
3
4
5

Joinメソッドとの違い

Joinメソッドは、2つのコレクションを特定のキーに基づいて結合します。

これに対して、Concatメソッドは単純にコレクションを連結するだけです。

Joinメソッドは、リレーショナルデータベースの結合に似た動作をします。

以下のサンプルコードでは、Joinメソッドの使用例を示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        var students = new List<Student>
        {
            new Student { Id = 1, Name = "Alice" },
            new Student { Id = 2, Name = "Bob" }
        };
        var scores = new List<Score>
        {
            new Score { StudentId = 1, Value = 90 },
            new Score { StudentId = 2, Value = 85 }
        };
        var joinResult = from student in students
                         join score in scores on student.Id equals score.StudentId
                         select new { student.Name, score.Value };
        Console.WriteLine("Joinの結果:");
        foreach (var item in joinResult)
        {
            Console.WriteLine($"{item.Name}: {item.Value}");
        }
    }
}
class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
}
class Score
{
    public int StudentId { get; set; }
    public int Value { get; set; }
}
Joinの結果:
Alice: 90
Bob: 85

Zipメソッドとの違い

Zipメソッドは、2つのコレクションを要素ごとに結合し、新しいコレクションを生成します。

Concatメソッドは、コレクションを単純に連結するだけで、要素の組み合わせを行いません。

以下のサンプルコードでは、Zipメソッドの使用例を示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<int> numbers1 = new List<int> { 1, 2, 3 };
        List<string> numbers2 = new List<string> { "A", "B", "C" };
        var zipResult = numbers1.Zip(numbers2, (n, s) => $"{n}-{s}");
        Console.WriteLine("Zipの結果:");
        foreach (var item in zipResult)
        {
            Console.WriteLine(item);
        }
    }
}
Zipの結果:
1-A
2-B
3-C

SelectManyメソッドとの違い

SelectManyメソッドは、コレクションの各要素から新しいコレクションを生成し、それらをフラットに結合します。

Concatメソッドは、単に2つのコレクションを連結するだけです。

以下のサンプルコードでは、SelectManyメソッドの使用例を示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        var listOfLists = new List<List<int>>
        {
            new List<int> { 1, 2 },
            new List<int> { 3, 4 },
            new List<int> { 5, 6 }
        };
        var selectManyResult = listOfLists.SelectMany(x => x);
        Console.WriteLine("SelectManyの結果:");
        foreach (var item in selectManyResult)
        {
            Console.WriteLine(item);
        }
    }
}
SelectManyの結果:
1
2
3
4
5
6

このように、Concatメソッドは他の結合メソッドと異なる特性を持っており、用途に応じて使い分けることが重要です。

Concatメソッドの注意点

大量のデータを結合する際のメモリ使用量

Concatメソッドを使用して大量のデータを結合する場合、メモリ使用量に注意が必要です。

Concatメソッドは、結合した結果を新しいIEnumerable<T>として返しますが、元のコレクションのサイズが大きい場合、メモリに負担をかける可能性があります。

特に、非常に大きなコレクションを結合する場合は、メモリ不足に陥るリスクがあります。

以下のサンプルコードでは、大量のデータを結合する際の注意点を示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        // 大量のデータを生成
        var largeList1 = Enumerable.Range(1, 1000000).ToList();
        var largeList2 = Enumerable.Range(1000001, 1000000).ToList();
        // Concatメソッドを使用して結合
        var result = largeList1.Concat(largeList2);
        Console.WriteLine("結合したデータの数: " + result.Count());
    }
}
結合したデータの数: 2000000

パフォーマンスの最適化

Concatメソッドを使用する際は、パフォーマンスの最適化も考慮する必要があります。

特に、頻繁に結合を行う場合、結合するコレクションのサイズや内容を事前に確認し、必要に応じてフィルタリングやソートを行うことで、パフォーマンスを向上させることができます。

以下のサンプルコードでは、フィルタリングを行った後にConcatメソッドを使用しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<int> list1 = Enumerable.Range(1, 1000000).ToList();
        List<int> list2 = Enumerable.Range(500000, 500000).ToList();
        // フィルタリングを行ってから結合
        var result = list1.Where(x => x % 2 == 0).Concat(list2.Where(x => x % 2 != 0));
        Console.WriteLine("結合したデータの数: " + result.Count());
    }
}
結合したデータの数: 750000

コレクションの変更が反映されない点

Concatメソッドは、元のコレクションを変更することなく、新しいコレクションを生成します。

したがって、元のコレクションに対する変更は、Concatメソッドの結果には反映されません。

この特性を理解しておかないと、意図しない結果を招く可能性があります。

以下のサンプルコードでは、元のコレクションを変更した場合の挙動を示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<int> list1 = new List<int> { 1, 2, 3 };
        List<int> list2 = new List<int> { 4, 5, 6 };
        var result = list1.Concat(list2);
        // 元のコレクションを変更
        list1.Add(7);
        Console.WriteLine("Concatの結果:");
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}
Concatの結果:
1
2
3
4
5
6

Concatメソッドの遅延実行について

Concatメソッドは、遅延実行を行います。

これは、結果が必要になるまで実際の結合処理が行われないことを意味します。

遅延実行は、パフォーマンスを向上させる一方で、コレクションの状態が変化する可能性があるため、注意が必要です。

以下のサンプルコードでは、遅延実行の特性を示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<int> list1 = new List<int> { 1, 2, 3 };
        List<int> list2 = new List<int> { 4, 5, 6 };
        var result = list1.Concat(list2);
        // 結果を出力する前に元のコレクションを変更
        list1.Add(7);
        Console.WriteLine("Concatの結果:");
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}
Concatの結果:
1
2
3
7
4
5
6

このように、Concatメソッドの遅延実行により、元のコレクションの変更が結果に影響を与えることがあります。

遅延実行の特性を理解し、適切に使用することが重要です。

まとめ

この記事では、C#のConcatメソッドについて、その基本的な使い方や動作の詳細、応用例、他の結合メソッドとの比較、注意点などを詳しく解説しました。

Concatメソッドは、複数のコレクションを簡単に結合できる便利な機能であり、特にデータの集約や表示に役立ちます。

これを活用することで、より効率的にデータを操作し、プログラムの可読性を向上させることが可能です。

今後は、実際のプロジェクトやデータ処理の場面でConcatメソッドを積極的に活用し、他のLINQメソッドと組み合わせて、より効果的なデータ操作を行ってみてください。

関連記事

Back to top button