Javaでは、Arrays.equals()
2つの基本配列の内容を簡単に比較できます(すべての基本タイプでオーバーロードを使用できます)。
C#にそのようなものはありますか?C#で2つの配列の内容を比較する「魔法の」方法はありますか?
Javaでは、Arrays.equals()
2つの基本配列の内容を簡単に比較できます(すべての基本タイプでオーバーロードを使用できます)。
C#にそのようなものはありますか?C#で2つの配列の内容を比較する「魔法の」方法はありますか?
回答:
使用できますEnumerable.SequenceEqual
。これは、IEnumerable<T>
配列だけでなく、すべてので機能します。
SequenceEqual
現在の実装では、ソースの長さが異なるだけでソースの1つを完全に列挙する可能性があるため、パフォーマンスに関しては適切な選択ではない可能性があります。配列を使用する場合は、Length
最初に等価性をチェックして、異なる長さの配列を列挙して最終的に生成を回避することができますfalse
。
LINQで使用Enumerable.SequenceEqual
します。
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
new int[] {1}.SequenceEquals(null) == false
また、配列(およびタプル)の場合は、.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
}
a.StructuralCompare(b)
ますか?
以下のために、.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));
SequenceEqual
2つの条件または条件を満たす場合にのみtrueを返します。
順序に関係なく同じ要素が含まれているかどうかを確認するだけで、問題は次のタイプの場合
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);
異なる結果が得られます。
私の場合、配列のローカルコピーがあり、元の配列から何かが削除されているかどうかを確認したいので、この方法を使用します。
SequenceEqual
。
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.
}
}
a1 = { 1, 1 }
との場合a2 = { 1, 2 }
、最初のテストで間違った結果が返されます。リターンステートメントはreturn array1.Count() == array2.Count() && !array1.Except(array2).Any() && !array2.Except(array1).Any();
一部のアプリケーションの方が良い場合があります:
string.Join(",", arr1) == string.Join(",", arr2)
この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)
);
要素ごとに比較しますか?どうですか
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つの例を組み合わせたものです)
true
ありnull
ます)と配列(クラッシュします)は処理しません。
私はビジュアルスタジオでこれを行い、それは完全に機能しました。配列をインデックスごとに短いコードと比較します。
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です。
null
配列(クラッシュします)、配列(あまりにもクラッシュします)を処理せず、OPが要求したもの以外の何かを行います。彼は、いくつのアイテムが異なるか一致するかを数えることなく、平等を知るように求めただけです。
配列が等しいと仮定すると、両方の配列の等しい要素が同じインデックスにあり、SequenceEqual
答えと答えがありIStructuralEquatable
ます。。
ただし、どちらにもパフォーマンス上の欠点があります。
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;
}
しかし、もちろん、それは配列の等価性をチェックする「魔法の方法」でもありません。
そのため、現在、いいえ、実際にArrays.equals()
は.Net にJava に相当するものはありません。
null
。あなたの言いたいことは何ですか?