Java'da, Arrays.equals()
iki temel dizinin içeriğini kolayca karşılaştırmaya izin verir (tüm temel türler için aşırı yükler mevcuttur).
C # 'da böyle bir şey var mı? C # iki dizinin içeriğini karşılaştırmak için herhangi bir "sihirli" yolu var mı?
Java'da, Arrays.equals()
iki temel dizinin içeriğini kolayca karşılaştırmaya izin verir (tüm temel türler için aşırı yükler mevcuttur).
C # 'da böyle bir şey var mı? C # iki dizinin içeriğini karşılaştırmak için herhangi bir "sihirli" yolu var mı?
Yanıtlar:
Kullanabilirsin Enumerable.SequenceEqual
. Bu IEnumerable<T>
sadece diziler için değil, her dizide işe yarar.
SequenceEqual
akıllıca bir iyi performans performansı olmayabilir, çünkü mevcut uygulaması kaynaklarından birini yalnızca uzunluk olarak farklılık gösterirse tam olarak numaralandırabilir. Length
Dizilerle, farklı uzunluklardaki dizilerin sadece sonuç vermesi için numaralandırılmasından kaçınmak için önce eşitliği kontrol edebiliriz false
.
Kullanım Enumerable.SequenceEqual
içinde 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
new int[] {1}.SequenceEquals(null) == false
Ayrıca diziler (ve tuples) için .NET 4.0'dan yeni arabirimler kullanabilirsiniz: IStructuralComparable ve IStructuralEquatable . Bunları kullanarak sadece dizilerin eşitliğini kontrol etmekle kalmaz, aynı zamanda onları da karşılaştırabilirsiniz.
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)
mı?
İçin .NET 4.0 ve üzeri kullanmakta aracılığıyla dizideki eleman veya dizilerini karşılaştırabilirsiniz StructuralComparisons türü:
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
yalnızca iki koşul veya karşılandığında doğru dönecektir.
Sadece siparişlerine bakılmaksızın aynı öğeleri içerip içermediklerini kontrol etmek istiyorsanız ve sorununuz türü
Değer2, değerler1'de yer alan tüm değerleri içeriyor mu?
LINQ genişletme yöntemini kullanabilir Enumerable.Except
ve ardından sonucun herhangi bir değeri olup olmadığını kontrol edebilirsiniz. İşte bir örnek
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
}
Ayrıca bunu kullanarak farklı öğeleri otomatik olarak da alabilirsiniz. Bir taşla iki kuş.
Kodunuzu bu şekilde yürütürseniz unutmayın
var result = values2.Except(values1);
farklı sonuçlar elde edersiniz.
Benim durumumda bir dizinin yerel bir kopyası var ve bu yöntemi kullanmak için bir şey orijinal diziden kaldırılmış olup olmadığını kontrol etmek istiyorum.
SequenceEqual
.
Birim testleri için CollectionAssert.AreEqual
yerine kullanabilirsiniz Assert.AreEqual
.
Muhtemelen en kolay yol budur.
null
Girdileri zarif bir şekilde işlemek ve öğelerin sırasını yoksaymak istiyorsanız , aşağıdaki çözümü deneyin:
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();
}
}
Test kodu şuna benzer:
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 }
ve a2 = { 1, 2 }
sonra ilk test yanlış sonucu döndürür. İade beyanı şu olmalıdırreturn array1.Count() == array2.Count() && !array1.Except(array2).Any() && !array2.Except(array1).Any();
Bazı uygulamalar için daha iyi olabilir:
string.Join(",", arr1) == string.Join(",", arr2)
Bu LINQ çözümü, performansta SequenceEquals ile nasıl karşılaştırılacağından emin değildir. Ancak farklı dizi uzunluklarını işler ve .All tüm dizi boyunca yineleme yapmadan eşit olmayan ilk öğeden çıkar.
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)
);
elementwise karşılaştırmak? ne dersin
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) koşulunu a ve b'de karşılaştırmak istediğiniz herhangi bir şeyle değiştirin.
(bu, MSDN geliştiricisi Linq örneklerinden iki örneği birleştirir )
true
) ve null
dizileri (çökecek) işlemez .
Bunu görsel stüdyolarda yaptım ve mükemmel çalıştı; dizinin dizine göre dizini bu kodla karşılaştırır.
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);
}
çıktı; Eşleşen sayılar 7'dir Eşleşmeyen sayılar 3'tür
null
dizileri ( çökecek), dizileri (çok çökecek) işlemez ve OP'nin istediklerinden başka bir şey yapar. Kaç öğenin farklı olduğunu veya eşleştiğini saymadan sadece eşitliği bilmek istedi.
İki dizide aynı dizinler eşit elemanları dizisi eşitlik aracı varsayarsak, orada SequenceEqual
cevap ve IStructuralEquatable
cevap .
Ancak her ikisinin de performans açısından dezavantajları vardır.
SequenceEqual
mevcut uygulama, dizilerin farklı uzunluklara sahip olduğu durumlarda kısayol oluşturmaz ve bu nedenle, öğelerinden her birini karşılaştırarak bunlardan birini tamamen numaralandırabilir.
IStructuralEquatable
jenerik değildir ve karşılaştırılan her değerin boksuna neden olabilir. Dahası, kullanımı çok kolay değildir ve zaten onu gizleyen bazı yardımcı yöntemleri kodlamayı gerektirir.
Performans açısından akıllıca bir şey kullanmak daha iyi olabilir:
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;
}
Ama tabii ki, bu dizi eşitliğini kontrol etmenin "sihirli yolu" da değil.
Yani, şu anda, Arrays.equals()
.Net'teki Java'ya gerçekten eşdeğer değil .
null
. Amacın ne?