配列のすべての要素が一致しているか判定する - C#

配列のすべての要素が一致しているか判定するコードを紹介します。

概要

2つの配列があるとき、それぞれの配列の要素が一致しているかを判定するには、ループで配列の要素をひとつづつ比較するのがオーソドックスな方法です。 ループで比較する方法はコードの量が増えるため、ループ処理以外で配列の要素を比較するコードを紹介します。

配列の一致を比較する方法

配列の一致を比較する方法は以下があります。
  • ループで配列のそれぞれの要素を比較する
  • ArrayオブジェクトのSequenceEqualメソッドを利用する
  • IStructuralEquatable インターフェイスのEqualsメソッドを利用する
  • unsafeコードでバイト比較する方法 (バイト配列のみ)
  • memcmp Windows API (Visual C++ ランタイム msvcrt)を利用する方法 (バイト配列のみ)

この記事では、ループで比較する方法、SequenceEqualメソッドを利用する方法、 IStructuralEquatable インターフェイスを利用する方法、memcmp Windows APIを利用する方法を紹介します。

プログラム例:int配列の一致比較

UI

下図のフォームを作成します。MultilineプロパティをTrueに設定したテキストボックスを1つとボタンを3つ配置します。

コード

以下のコードを記述します。3つのボタンのClickイベントを実装します。
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ArrayCompare
{
  public partial class FormValueCompare : Form
  {
    private int[] ArrayData1 = { 4, 8, 2, 6, 5, 4 };
    private int[] ArrayData2 = { 1, 8, 2, 2, 4, 8 };
    private int[] ArrayData3 = { 4, 8, 2, 6, 5, 4 };

    public FormValueCompare()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      bool equal = true;
      if (ArrayData1.Length == ArrayData2.Length) {
        for (int i = 0; i < ArrayData1.Length; i++) {
          if (ArrayData1[i] == ArrayData2[i]) {
          }
          else {
            equal = false;
            break;
          }
        }
      }
      else {
        equal = false;
      }

      if (equal == true) {
        textBox1.Text += "ArrayData1 と ArrayData2 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "ArrayData1 と ArrayData2 では一致しない要素があります。\r\n";
      }
      
      //

      equal = true;
      if (ArrayData1.Length == ArrayData3.Length) {
        for (int i = 0; i < ArrayData1.Length; i++) {
          if (ArrayData1[i] == ArrayData3[i]) {
          }
          else {
            equal = false;
            break;
          }
        }
      }
      else {
        equal = false;
      }

      if (equal == true) {
        textBox1.Text += "ArrayData1 と ArrayData3 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "ArrayData1 と ArrayData3 では一致しない要素があります。\r\n";
      }
    }

    private void button2_Click(object sender, EventArgs e)
    {
      bool equal1 = ArrayData1.SequenceEqual(ArrayData2);
      if (equal1 == true) {
        textBox1.Text += "ArrayData1 と ArrayData2 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "ArrayData1 と ArrayData2 では一致しない要素があります。\r\n";
      }

      bool equal2 = ArrayData1.SequenceEqual(ArrayData3);
      if (equal2 == true) {
        textBox1.Text += "ArrayData1 と ArrayData3 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "ArrayData1 と ArrayData3 では一致しない要素があります。\r\n";
      }
    }

    private void button3_Click(object sender, EventArgs e)
    {
      IStructuralEquatable se1 = (IStructuralEquatable)ArrayData1;
      bool equal1 = se1.Equals(ArrayData2,StructuralComparisons.StructuralEqualityComparer);
      if (equal1 == true) {
        textBox1.Text += "ArrayData1 と ArrayData2 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "ArrayData1 と ArrayData2 では一致しない要素があります。\r\n";
      }

      bool equal2 = se1.Equals(ArrayData3, StructuralComparisons.StructuralEqualityComparer);
      if (equal2 == true) {
        textBox1.Text += "ArrayData1 と ArrayData3 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "ArrayData1 と ArrayData3 では一致しない要素があります。\r\n";
      }
    }
  }
}

解説

button1

比較する2つの配列の長さを比較します。それぞれの配列の長さが違う場合は一致していませんので、 equal変数をfalseに設定します。 2つの配列の長さが一致している場合は、forループでそれぞれの配列の要素を比較します。 配列の要素の不一致が見つかった段階で、equal変数をfalseに設定し、ループを中断します。

equal変数がfalseであれば、配列は一致しておらず、 equal変数がtrueであれば、すべての配列の要素が一致しており、2つの配列は一致していると判定できます。
  bool equal = true;
  if (ArrayData1.Length == ArrayData2.Length) {
    for (int i = 0; i < ArrayData1.Length; i++) {
      if (ArrayData1[i] == ArrayData2[i]) {
      }
      else {
        equal = false;
        break;
      }
    }
  }
  else {
    equal = false;
  }

  if (equal == true) {
    textBox1.Text += "ArrayData1 と ArrayData2 のすべての要素が一致しています。\r\n";
  }
  else {
    textBox1.Text += "ArrayData1 と ArrayData2 では一致しない要素があります。\r\n";
  }

button2

配列(Arrayオブジェクト)のSequenceEqual() メソッドを呼び出します。SequenceEqualメソッドの第一引数に比較したい配列変数を与えます。
配列の要素が一致していれば、SequenceEqual()メソッドの戻り値がTrueになります。
  bool equal1 = ArrayData1.SequenceEqual(ArrayData2);
  if (equal1 == true) {
    textBox1.Text += "ArrayData1 と ArrayData2 のすべての要素が一致しています。\r\n";
  }
  else {
    textBox1.Text += "ArrayData1 と ArrayData2 では一致しない要素があります。\r\n";
  }

button3

配列変数をIStructuralEquatable インターフェイスの変数にキャストして代入します。
  IStructuralEquatable se1 = (IStructuralEquatable)ArrayData1;

IStructuralEquatable インターフェイスの変数のEquals()メソッドを呼び出します。 Equalsメソッドの第一引数に比較したい配列変数を与えます。第二引数に変数を比較するIEqualityComparerオブジェクトを与えます。
今回の例では、StructuralComparisons.StructuralEqualityComparerを与えています。
2つの配列の要素が一致していた場合は、Equalsメソッドの戻り値がtrueになります。
  bool equal1 = se1.Equals(ArrayData2,StructuralComparisons.StructuralEqualityComparer);

  IStructuralEquatable se1 = (IStructuralEquatable)ArrayData1;
  bool equal1 = se1.Equals(ArrayData2,StructuralComparisons.StructuralEqualityComparer);
  if (equal1 == true) {
    textBox1.Text += "ArrayData1 と ArrayData2 のすべての要素が一致しています。\r\n";
  }
  else {
    textBox1.Text += "ArrayData1 と ArrayData2 では一致しない要素があります。\r\n";
  }

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


[button1]をクリックします。forループで2つの配列を比較した結果が表示されます。
ArrayData1とArrayData2は一致しておらず、ArrayData1とArrayData3は一致している旨のメッセージが表示されます。


[button2]をクリックします。SequenceEqualメソッドで2つの配列を比較した結果が表示されます。
ArrayData1とArrayData2は一致しておらず、ArrayData1とArrayData3は一致している旨のメッセージが表示されます。


[button3]をクリックします。IStructuralEquatableインターフェイスのEqualsメソッドで2つの配列を比較した結果が表示されます。
ArrayData1とArrayData2は一致しておらず、ArrayData1とArrayData3は一致している旨のメッセージが表示されます。

プログラム例:string配列の一致比較

UI

下図のフォームを作成します。先の例と同様にMultilineプロパティをTrueに設定したテキストボックスとボタンを3つ配置します。

コード

以下のコードを記述します。
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ArrayCompare
{
  public partial class FormStringValueCompare : Form
  {
    private string[] ArrayData1 = { "ぺんぎんクッキー","らくだキャラメル","しろくまアイス","かるがもサブレ" };
    private string[] ArrayData2 = { "きつねクッキー", "らくだキャラメル", "くじらケーキ", "かるがもサブレ" };
    private string[] ArrayData3 = { "ぺんぎんクッキー", "らくだキャラメル", "しろくまアイス", "かるがもサブレ" };

    public FormStringValueCompare()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      bool equal = true;
      if (ArrayData1.Length == ArrayData2.Length) {
        for (int i = 0; i < ArrayData1.Length; i++) {
          if (ArrayData1[i] == ArrayData2[i]) {
          }
          else {
            equal = false;
            break;
          }
        }
      }
      else {
        equal = false;
      }

      if (equal == true) {
        textBox1.Text += "ArrayData1 と ArrayData2 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "ArrayData1 と ArrayData2 では一致しない要素があります。\r\n";
      }

      //

      equal = true;
      if (ArrayData1.Length == ArrayData3.Length) {
        for (int i = 0; i < ArrayData1.Length; i++) {
          if (ArrayData1[i] == ArrayData3[i]) {
          }
          else {
            equal = false;
            break;
          }
        }
      }
      else {
        equal = false;
      }

      if (equal == true) {
        textBox1.Text += "ArrayData1 と ArrayData3 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "ArrayData1 と ArrayData3 では一致しない要素があります。\r\n";
      }
    }

    private void button2_Click(object sender, EventArgs e)
    {
      bool equal1 = ArrayData1.SequenceEqual(ArrayData2);
      if (equal1 == true) {
        textBox1.Text += "ArrayData1 と ArrayData2 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "ArrayData1 と ArrayData2 では一致しない要素があります。\r\n";
      }

      bool equal2 = ArrayData1.SequenceEqual(ArrayData3);
      if (equal2 == true) {
        textBox1.Text += "ArrayData1 と ArrayData3 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "ArrayData1 と ArrayData3 では一致しない要素があります。\r\n";
      }
    }

    private void button3_Click(object sender, EventArgs e)
    {
      IStructuralEquatable se1 = (IStructuralEquatable)ArrayData1;
      bool equal1 = se1.Equals(ArrayData2, StructuralComparisons.StructuralEqualityComparer);
      if (equal1 == true) {
        textBox1.Text += "ArrayData1 と ArrayData2 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "ArrayData1 と ArrayData2 では一致しない要素があります。\r\n";
      }

      bool equal2 = se1.Equals(ArrayData3, StructuralComparisons.StructuralEqualityComparer);
      if (equal2 == true) {
        textBox1.Text += "ArrayData1 と ArrayData3 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "ArrayData1 と ArrayData3 では一致しない要素があります。\r\n";
      }
    }
  }
}

解説

比較する配列がstring型の配列ですが、コード自体は先のint配列のコードと同じコードです。

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


[button1]をクリックします。forループで2つの配列を比較した結果が表示されます。
ArrayData1とArrayData2は一致しておらず、ArrayData1とArrayData3は一致している旨のメッセージが表示されます。


[button2]をクリックします。SequenceEqualメソッドで2つの配列を比較した結果が表示されます。
ArrayData1とArrayData2は一致しておらず、ArrayData1とArrayData3は一致している旨のメッセージが表示されます。


[button3]をクリックします。IStructuralEquatableインターフェイスのEqualsメソッドで2つの配列を比較した結果が表示されます。
ArrayData1とArrayData2は一致しておらず、ArrayData1とArrayData3は一致している旨のメッセージが表示されます。

プログラム例:memcmp を利用する例

Visual C++ ランタイム msvcrt.dllの memcmp関数を利用するコードです。

UI

コード

以下のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ArrayCompare
{
  public partial class FormMemcmpCompare : Form
  {
    [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern int memcmp(byte[] b1, byte[] b2, UIntPtr count);

    private byte[] data1 = { 4, 8, 2, 9, 16, 4 };
    private byte[] data2 = { 1, 3, 2, 9, 8, 3 };
    private byte[] data3 = { 4, 8, 2, 9, 16, 4 };

    public FormMemcmpCompare()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      bool equal = true;
      if (data1.Length == data2.Length) {
        for (int i = 0; i < data1.Length; i++) {
          if (data1[i] == data2[i]) {
          }
          else {
            equal = false;
            break;
          }
        }
      }
      else {
        equal = false;
      }

      if (equal == true) {
        textBox1.Text += "data1 と data2 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "data1 と data2 では一致しない要素があります。\r\n";
      }

      //

      equal = true;
      if (data1.Length == data3.Length) {
        for (int i = 0; i < data1.Length; i++) {
          if (data1[i] == data3[i]) {
          }
          else {
            equal = false;
            break;
          }
        }
      }
      else {
        equal = false;
      }

      if (equal == true) {
        textBox1.Text += "data1 と data3 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "data1 と data3 では一致しない要素があります。\r\n";
      }
    }

    private void button2_Click(object sender, EventArgs e)
    {
      UIntPtr length1 = new UIntPtr((uint)data1.Length);

      int result1 = memcmp(data1, data2, length1);

      if (result1 == 0) {
        textBox1.Text += "data1 と data2 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "data1 と data2 では一致しない要素があります。\r\n";
      }

      //
      int result2 = memcmp(data1, data3, length1);

      if (result2 == 0) {
        textBox1.Text += "data1 と data3 のすべての要素が一致しています。\r\n";
      }
      else {
        textBox1.Text += "data1 と data3 では一致しない要素があります。\r\n";
      }
    }
  }
}

書式:memcmp

memcmp関数の書式は次の通りです。
memcmp( [byte[]型の比較する配列1], [byte[]型の比較する配列2], [比較する配列の長さ] )

解説

button1

button1は先のプログラム例と同様の処理を実装しています。2つの配列の長さを比較し、 配列の長さが同じ場合はループで配列の要素同士を比較し、すべての要素が一致した場合、 要素が一致した旨のメッセージをテキストボックスに表示します。
  bool equal = true;
  if (data1.Length == data2.Length) {
    for (int i = 0; i < data1.Length; i++) {
      if (data1[i] == data2[i]) {
      }
      else {
        equal = false;
        break;
      }
    }
  }
  else {
    equal = false;
  }

  if (equal == true) {
    textBox1.Text += "data1 と data2 のすべての要素が一致しています。\r\n";
  }
  else {
    textBox1.Text += "data1 と data2 では一致しない要素があります。\r\n";
  }

button2

DllImport属性を記述し、msvcrt.dll から memcmp 関数をインポートします。
  [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
  static extern int memcmp(byte[] b1, byte[] b2, UIntPtr count);

memcmp関数を呼び出します。第一引数、第二引数に比較したいbyte配列の変数を与えます。第三引数には、配列の長さ(バイト数)を与えます。
第三引数はUIntPtr型のため、new演算子を利用してオブジェクトを作成して値を用意します。
  UIntPtr length1 = new UIntPtr((uint)data1.Length);

  int result1 = memcmp(data1, data2, length1);

  if (result1 == 0) {
    textBox1.Text += "data1 と data2 のすべての要素が一致しています。\r\n";
  }
  else {
    textBox1.Text += "data1 と data2 では一致しない要素があります。\r\n";
  }
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2023-02-14
iPentec all rights reserverd.