配列のすべての要素が一致しているか判定する - 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を愛用