Trong Java, Arrays.equals()
cho phép dễ dàng so sánh nội dung của hai mảng cơ bản (quá tải có sẵn cho tất cả các loại cơ bản).
Có một điều như vậy trong C #? Có cách nào "kỳ diệu" để so sánh nội dung của hai mảng trong C # không?
Trong Java, Arrays.equals()
cho phép dễ dàng so sánh nội dung của hai mảng cơ bản (quá tải có sẵn cho tất cả các loại cơ bản).
Có một điều như vậy trong C #? Có cách nào "kỳ diệu" để so sánh nội dung của hai mảng trong C # không?
Câu trả lời:
Bạn có thể sử dụng Enumerable.SequenceEqual
. Điều này làm việc cho bất kỳ IEnumerable<T>
, không chỉ mảng.
SequenceEqual
có thể không phải là một lựa chọn tốt về hiệu suất, vì việc triển khai hiện tại của nó có thể liệt kê đầy đủ một trong các nguồn của nó nếu chúng chỉ khác nhau theo độ dài. Với các mảng, chúng ta có thể kiểm tra Length
sự bằng nhau trước tiên, để tránh liệt kê các mảng có độ dài khác nhau chỉ để đạt năng suất cuối cùng false
.
Sử dụng Enumerable.SequenceEqual
trong 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
Ngoài ra, đối với các mảng (và bộ dữ liệu), bạn có thể sử dụng các giao diện mới từ .NET 4.0: IStructuralComparable và IStructuralEquitable . Sử dụng chúng, bạn không chỉ kiểm tra sự bằng nhau của mảng mà còn so sánh chúng.
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)
?
Đối với .NET 4.0 và cao hơn bạn có thể so sánh các yếu tố trong mảng hoặc tuples qua sử dụng StructuralComparisons loại:
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
sẽ chỉ trả về đúng nếu hai điều kiện hoặc đáp ứng.
Nếu bạn chỉ muốn kiểm tra xem chúng có chứa các phần tử giống nhau không phụ thuộc vào thứ tự của chúng và vấn đề của bạn thuộc loại
Giá trị2 có chứa tất cả các giá trị có trong giá trị1 không?
bạn có thể sử dụng phương pháp mở rộng LINQ Enumerable.Except
và sau đó kiểm tra xem kết quả có giá trị nào không. Đây là một ví dụ
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
}
Và cũng bằng cách sử dụng này, bạn sẽ nhận được các mặt hàng khác nhau cũng tự động. Hai con chim với một đá.
Hãy ghi nhớ, nếu bạn thực thi mã của mình như thế này
var result = values2.Except(values1);
bạn sẽ nhận được kết quả khác nhau.
Trong trường hợp của tôi, tôi có một bản sao cục bộ của một mảng và muốn kiểm tra xem có gì đã bị xóa khỏi mảng ban đầu hay không nên tôi sử dụng phương thức này.
SequenceEqual
.
Đối với các bài kiểm tra đơn vị, bạn có thể sử dụng CollectionAssert.AreEqual
thay vì Assert.AreEqual
.
Nó có lẽ là cách dễ nhất.
Nếu bạn muốn xử lý các null
đầu vào một cách duyên dáng và bỏ qua thứ tự của các mục, hãy thử giải pháp sau:
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();
}
}
Mã kiểm tra trông như:
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 }
và a2 = { 1, 2 }
, thì thử nghiệm đầu tiên trả về kết quả sai. Tuyên bố trở lại phải làreturn array1.Count() == array2.Count() && !array1.Except(array2).Any() && !array2.Except(array1).Any();
Đối với một số ứng dụng có thể tốt hơn:
string.Join(",", arr1) == string.Join(",", arr2)
Giải pháp LINQ này hoạt động, không chắc nó so sánh hiệu năng với SequenceEquals như thế nào. Nhưng nó xử lý các độ dài mảng khác nhau và. ALL sẽ thoát trên mục đầu tiên không bằng mà không lặp qua toàn bộ mảng.
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)
);
so sánh nguyên tố? Thế còn
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)");
}
Thay thế điều kiện (a == b) bằng bất cứ điều gì bạn muốn so sánh trong a và b.
(điều này kết hợp hai ví dụ từ các mẫu Linq của nhà phát triển MSDN )
true
) và null
mảng (sẽ sụp đổ).
Tôi đã làm điều này trong các studio hình ảnh và nó hoạt động hoàn hảo; so sánh chỉ số mảng theo chỉ số với mã ngắn này.
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);
}
đầu ra sẽ là; Các số phù hợp là 7 Các số không khớp là 3
null
mảng (cũng sẽ sụp đổ) và nó làm một cái gì đó khác với những gì OP yêu cầu. Ông chỉ yêu cầu được biết bình đẳng, mà không tính có bao nhiêu mặt hàng khác nhau hoặc phù hợp.
Giả sử bình đẳng mảng có nghĩa là cả hai mảng có các phần tử bằng nhau ở các chỉ mục bằng nhau, có SequenceEqual
câu trả lời và IStructuralEquatable
câu trả lời .
Nhưng cả hai đều có nhược điểm, hiệu suất khôn ngoan.
SequenceEqual
việc thực hiện hiện tại sẽ không tắt khi các mảng có độ dài khác nhau và do đó, nó có thể liệt kê hoàn toàn một trong số chúng, so sánh từng yếu tố của nó.
IStructuralEquatable
không chung chung và có thể gây ra quyền anh của từng giá trị so sánh. Hơn nữa, nó không đơn giản để sử dụng và đã yêu cầu mã hóa một số phương thức trợ giúp để ẩn nó đi.
Nó có thể tốt hơn, hiệu suất khôn ngoan, để sử dụng một cái gì đó như:
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;
}
Nhưng tất nhiên, đó không phải là một "cách kỳ diệu" để kiểm tra sự bằng nhau của mảng.
Vì vậy, hiện tại, không, thực sự không có tương đương với Java Arrays.equals()
trong .Net.
null
. Quan điểm của bạn là gì?