web-dev-qa-db-ja.com

C#で配列を比較する最も簡単な方法

Javaでは、Arrays.equals()を使用すると、2つの基本配列の内容を簡単に比較できます(オーバーロードはすべての基本型で利用可能です)。

C#にはそのようなものがありますか? C#で2つの配列の内容を比較する「魔法の」方法はありますか?

145
asmo

SequenceEqual を使用できます。これは、配列だけでなく、どのIEnumerable<T>でも機能します。

220
Quartermeister

SequenceEqual in LINQ を使用します。

int[] arr1 = new int[] { 1,2,3};
int[] arr2 = new int[] { 3,2,1 };

Console.WriteLine(arr1.SequenceEqual(arr2)); // false
Console.WriteLine(arr1.Reverse().SequenceEqual(arr2)); // true
58
John Buchanan

また、配列(およびタプル)の場合、.NET 4.0の新しいインターフェイス IStructuralComparable および IStructuralEquatable を使用できます。それらを使用すると、配列の等価性をチェックできるだけでなく、比較することもできます。

static class StructuralExtensions
{
    public static bool StructuralEquals<T>(this T a, T b)
        where T : IStructuralEquatable
    {
        return a.Equals(b, StructuralComparisons.StructuralEqualityComparer);
    }

    public static int StructuralCompare<T>(this T a, T b)
        where T : IStructuralComparable
    {
        return a.CompareTo(b, StructuralComparisons.StructuralComparer);
    }
}

{
    var a = new[] { 1, 2, 3 };
    var b = new[] { 1, 2, 3 };
    Console.WriteLine(a.Equals(b)); // False
    Console.WriteLine(a.StructuralEquals(b)); // True
}
{
    var a = new[] { 1, 3, 3 };
    var b = new[] { 1, 2, 3 };
    Console.WriteLine(a.StructuralCompare(b)); // 1
}
27
desco

。NET 4.0以降では、 StructuralComparisons タイプ:

object[] a1 = { "string", 123, true };
object[] a2 = { "string", 123, true };

Console.WriteLine (a1 == a2);        // False (because arrays is reference types)
Console.WriteLine (a1.Equals (a2));  // False (because arrays is reference types)

IStructuralEquatable se1 = a1;
//Next returns True
Console.WriteLine (se1.Equals (a2, StructuralComparisons.StructuralEqualityComparer)); 
17
Yuliia Ashomok

SequenceEqualは、2つの条件または条件を満たす場合にのみtrueを返します。

  1. それらには同じ要素が含まれています。
  2. 要素は同じ順序です。

順序に関係なく同じ要素が含まれているかどうかだけを確認したい場合、問題のタイプは

Values2には、values1に含まれるすべての値が含まれていますか?

lINQ拡張メソッドEnumerable.Exceptを使用して、結果に値があるかどうかを確認できます。ここに例があります

int[] values1 = { 1, 2, 3, 4 };
int[] values2 = { 1, 2, 5 };
var result = values1.Except(values2);
if(result.Count()==0)
{
   //They are the same
}
else
{
    //They are different
}

また、これを使用すると、さまざまなアイテムも自動的に取得されます。一石二鳥。

このようなコードを実行する場合は、覚えておいてください

var result = values2.Except(values1);

異なる結果が得られます。

私の場合、配列のローカルコピーがあり、元の配列から何かが削除されたかどうかを確認したいので、この方法を使用します。

12
John Demetriou

単体テストでは、CollectionAssert.AreEqualの代わりにAssert.AreEqualを使用できます。

これがおそらく最も簡単な方法です。

7
Paris Qian Sen

null入力を適切に処理し、アイテムの順序を無視する場合は、次の解決策を試してください。

static class Extensions
{
    public static bool ItemsEqual<TSource>(this TSource[] array1, TSource[] array2)
    {
        if (array1 == null && array2 == null)
            return true;
        if (array1 == null || array2 == null)
            return false;
        return array1.Count() == array2.Count() && !array1.Except(array2).Any();
    }
}

テストコードは次のようになります。

class Program
{
    static void Main(string[] args)
    {
        int[] a1 = new int[] { 1, 2, 3 };
        int[] a2 = new int[] { 3, 2, 1 };
        int[] a3 = new int[] { 1, 3 };
        int[] a4 = null;
        int[] a5 = null;
        int[] a6 = new int[0];

        Console.WriteLine(a1.ItemsEqual(a2)); // Output: True.
        Console.WriteLine(a2.ItemsEqual(a3)); // Output: False.
        Console.WriteLine(a4.ItemsEqual(a5)); // Output: True. No Exception.
        Console.WriteLine(a4.ItemsEqual(a3)); // Output: False. No Exception.
        Console.WriteLine(a5.ItemsEqual(a6)); // Output: False. No Exception.
    }
}
6
Harry He

一部のアプリケーションでは、より優れている場合があります。

string.Join(",", arr1) == string.Join(",", arr2)
3
alexkovelsky

このLINQソリューションは動作しますが、パフォーマンスがSequenceEqualsとどのように比較されるかはわかりません。しかし、異なる配列の長さを処理し、配列全体を反復することなく、等しくない最初の項目で.Allが終了します。

private static bool arraysEqual<T>(IList<T> arr1, IList<T> arr2)
        =>
            ReferenceEquals(arr1, arr2) || (
                arr1 != null && arr2 != null &&
                arr1.Count == arr2.Count &&
                arr1.Select((a, i) => arr2[i].Equals(a)).All(i => i)
            );
0
JoeS

要素ごとの比較?どう?

public void Linq78a()
{
 int[] numbers1 = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
 int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
 bool bb = numbers.Zip(numbers1, (a, b) => (a == b)).Any(p => !p);
 if (!bb) Console.WriteLine("Lists are equal (bb)");
   else Console.WriteLine("Lists are not equal (bb)");
}

(a == b)条件を、aとbで比較したいものに置き換えます。

(これは MSDN開発者Linqサンプル )の2つの例を組み合わせたものです

0
Goodies

配列が等しいと仮定すると、両方の配列が等しいインデックスで等しい要素を持つことを意味し、 SequenceEqual answerIStructuralEquatable answer があります。

しかし、パフォーマンスには欠点があります。

SequenceEqual現在の実装は、配列の長さが異なる場合にショートカットを作成しないため、各要素を比較して、配列の1つを完全に列挙できます。

IStructuralEquatableはジェネリックではなく、各比較値のボクシングを引き起こす可能性があります。さらに、使用するのはそれほど簡単ではなく、すでにいくつかのヘルパーメソッドをコーディングする必要があります。

次のようなものを使用する方が、パフォーマンス面で優れている場合があります。

bool ArrayEquals<T>(T[] first, T[] second)
{
    if (first == second)
        return true;
    if (first == null || second = null)
        return false;
    if (first.Length != second.Length)
        return false;
    for (var i = 0; i < first.Length; i++)
    {
        if (first[i] != second[i])
            return false;
    }
    return true;
}

しかし、もちろん、それは配列の等価性をチェックする「魔法の方法」ではありません。

ですから、現在のところ、いや、実際には.NetのJava Arrays.equals()に相当するものはありません。

0
Frédéric

私はこれをビジュアルスタジオで行いましたが、完全に機能しました。このコードを使用して、インデックスごとに配列を比較します。

private void compareButton_Click(object sender, EventArgs e)
        {
            int[] answer = { 1, 3, 4, 6, 8, 9, 5, 4, 0, 6 };
            int[] exam = { 1, 2, 3, 6, 8, 9, 5, 4, 0, 7 };

            int correctAnswers = 0;
            int wrongAnswers = 0;

            for (int index = 0; index < answer.Length; index++)
            {
                if (answer[index] == exam[index])
                {
                    correctAnswers += 1;
                }
                else
                {
                    wrongAnswers += 1;
                }
            }

            outputLabel.Text = ("The matching numbers are " + correctAnswers +
                "\n" + "The non matching numbers are " + wrongAnswers);
        }

出力は次のようになります。一致する番号は7です。一致しない番号は3です。

0
lucy