У Java Arrays.equals()
дозволяє легко порівнювати вміст двох основних масивів (перевантаження доступні для всіх основних типів).
Чи є таке в C #? Чи є якийсь "магічний" спосіб порівняння вмісту двох масивів у C #?
У Java Arrays.equals()
дозволяє легко порівнювати вміст двох основних масивів (перевантаження доступні для всіх основних типів).
Чи є таке в C #? Чи є якийсь "магічний" спосіб порівняння вмісту двох масивів у C #?
Відповіді:
Ви можете використовувати Enumerable.SequenceEqual
. Це працює для будь-яких IEnumerable<T>
, а не лише масивів.
SequenceEqual
може бути не дуже вдалим вибором продуктивності, оскільки його поточна реалізація може повністю перерахувати одне з джерел, якщо вони відрізняються лише довжиною. За допомогою масивів ми могли б перевірити Length
рівність спочатку, щоб уникнути перерахування масивів різної довжини лише для отримання кінцевих результатів false
.
Використання Enumerable.SequenceEqual
в 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
Також для масивів (та кортежів) ви можете використовувати нові інтерфейси від .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 всі значення, що містяться у значеннях1?
ви можете скористатися методом розширення 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
.
Для одиничних тестів можна використовувати CollectionAssert.AreEqual
замість Assert.AreEqual
.
Це, мабуть, найпростіший спосіб.
Якщо ви хочете 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 )
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
масиви (теж вийде з ладу), і він робить щось інше, ніж те, про що попросила ОП. Він лише попросив знати рівність, не рахуючи, скільки предметів відрізняються чи відповідають.
Якщо припустити рівність масиву означає, що обидва масиви мають рівні елементи при рівних індексах, є SequenceEqual
відповідь і IStructuralEquatable
відповідь .
Але в обох є недоліки, ефективність роботи.
SequenceEqual
поточна реалізація не буде ярликом, коли масиви мають різну довжину, і тому він може перерахувати один з них цілком, порівнюючи кожен його елемент.
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;
}
Але звичайно, це не є якимось "магічним способом" перевірки рівності масиву.
Отже, ні, насправді немає еквіваленту Java Arrays.equals()
в .Net.
null
. Який твій погляд?