DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

要素が重複しないようにして、複数の配列(またはコレクション)をマージする(和集合を取得する)

複数の配列(またはコレクション)をマージ(合併、連結、合体)する方法は「複数の配列(またはコレクション)をマージ(合併、連結、合体)する」で紹介しましたが、ここでは、例えば{ 1, 2, 1 }と{ 2, 3, 4 }をマージして{ 1, 2, 3, 4 }という配列を作るというように、同じ要素が含まれないようにしてマージする方法を紹介します。つまり、和集合を取得する方法ということになります。

ここで紹介しているコードは配列を例にしていますが、コレクションでも同じようにできます。

For文を使用する方法

最も基本的な方法は、For文を使った方法でしょう。以下の例では、マージする配列の要素を1つ1つ調べて、コレクションに存在していない要素だけをコレクションに追加するという方法でマージしています。

VB.NET
コードを隠すコードを選択
'マージする2つの配列
Dim ary1 As Integer() = New Integer() {1, 2, 1}
Dim ary2 As Integer() = New Integer() {2, 3, 4}

'マージした結果を入れるコレクション
'.NET Framework 2.0以降ならば、List(Of Integer)を使った方が良い
Dim mergedList As New System.Collections.ArrayList(ary1.Length + ary2.Length)

'ary1の要素をmergedListに追加する
Dim i As Integer
For Each i In ary1
    'まだ追加されていない要素だけを追加する
    If Not mergedList.Contains(i) Then
        mergedList.Add(i)
    End If
Next

'ary2の要素をmergedListに追加する
For Each i In ary2
    If Not mergedList.Contains(i) Then
        mergedList.Add(i)
    End If
Next

'配列に変換する
Dim mergedArray As Integer() = _
    DirectCast(mergedList.ToArray(GetType(Integer)), Integer())

'mergedArrayは{ 1, 2, 3, 4 }となる
C#
コードを隠すコードを選択
//マージする2つの配列
int[] ary1 = new int[] { 1, 2, 1 };
int[] ary2 = new int[] { 2, 3, 4 };

//マージした結果を入れるコレクション
//.NET Framework 2.0以降ならば、List<int>を使った方が良い
System.Collections.ArrayList mergedList =
    new System.Collections.ArrayList(ary1.Length + ary2.Length);

//ary1の要素をmergedListに追加する
foreach (int i in ary1)
{
    //まだ追加されていない要素だけを追加する
    if (!mergedList.Contains(i))
    {
        mergedList.Add(i);
    }
}

//ary2の要素をmergedListに追加する
foreach (int i in ary2)
{
    if (!mergedList.Contains(i))
    {
        mergedList.Add(i);
    }
}

//配列に変換する
int[] mergedArray = (int[])mergedList.ToArray(typeof(int));

//mergedArrayは{ 1, 2, 3, 4 }となる

Enumerable.Unionメソッドを使用する方法

.NET Framework 3.5以降でLinqを使えるのであれば、Enumerable.Unionメソッドを使って一発でできます。

VB.NET
コードを隠すコードを選択
'Imports System.Linq

'マージする2つの配列(コレクションでも可)
Dim ary1 As Integer() = New Integer() {1, 2, 1}
Dim ary2 As Integer() = New Integer() {2, 3, 4}

'2つの配列の和集合を作成して、配列に変換する
Dim mergedArray As Integer() = ary1.Union(ary2).ToArray()

'mergedArrayは{ 1, 2, 3, 4 }となる
C#
コードを隠すコードを選択
//using System.Linq;

//マージする2つの配列(コレクションでも可)
int[] ary1 = new int[] { 1, 2, 1 };
int[] ary2 = new int[] { 2, 3, 4 };

//2つの配列の和集合を作成して、配列に変換する
int[] mergedArray = ary1.Union(ary2).ToArray();

//mergedArrayは{ 1, 2, 3, 4 }となる

HashSet.UnionWithメソッドを使用する方法

.NET Framework 3.5からはHashSetクラスが追加されましたので、HashSet.UnionWithメソッドを使うこともできます。このメソッドはO(n)操作ですので、かなりパフォーマンスが良いです。

VB.NET
コードを隠すコードを選択
'Imports System.Collections.Generic

'マージする2つの配列(コレクションでも可)
Dim ary1 As Integer() = New Integer() {1, 2, 1}
Dim ary2 As Integer() = New Integer() {2, 3, 4}

'配列からHashSetオブジェクトを作成する
Dim hs1 As New HashSet(Of Integer)(ary1)
'ary2の要素を加える
hs1.UnionWith(ary2)

'HashSetを配列に変換する
Dim mergedArray As Integer() = New Integer(hs1.Count - 1) {}
hs1.CopyTo(mergedArray)

'mergedArrayは{ 1, 2, 3, 4 }となる
C#
コードを隠すコードを選択
//using System.Collections.Generic;

//マージする2つの配列(コレクションでも可)
int[] ary1 = new int[] { 1, 2, 1 };
int[] ary2 = new int[] { 2, 3, 4 };

//配列からHashSetオブジェクトを作成する
HashSet<int> hs1 = new HashSet<int>(ary1);
//ary2の要素を加える
hs1.UnionWith(ary2);

//HashSetを配列に変換する
int[] mergedArray = new int[hs1.Count];
hs1.CopyTo(mergedArray);

//mergedArrayは{ 1, 2, 3, 4 }となる

単純にマージしてから、重複した要素を取り除く

少し回りくどいですが、まず「複数の配列(またはコレクション)をマージ(合併、連結、合体)する」の方法で単純にマージしてから、「配列やコレクションの重複する要素を削除して、一意にする」の方法で重複した要素を取り除くという方法も考えられます。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。