В теги добавлено «.net», потому что этот метод может быть использован в других похожих языках .net.
Эван Плейс
3
Для всех, кто читает это, имейте в виду, что принятый ответ использует SequenceEqual. SequenceEqual не только проверяет, содержат ли они одинаковые данные, но также и содержат ли они одинаковые данные в одном и том же порядке
Джон Деметриу
Ответы:
262
Вы могли бы использовать Enumerable.SequenceEqual. Это работает для любых IEnumerable<T>, а не только массивов.
SequenceEqualне может быть хорошим выбором с точки зрения производительности, потому что его текущая реализация может полностью перечислять один из его источников, если они отличаются только длиной. С массивами мы могли бы Lengthсначала проверить равенство, чтобы избежать перечисления массивов разной длины, чтобы в конечном итоге дать результат false.
Имейте в виду, что это выбрасывает для нулевых аргументов, поэтому убедитесь, что не предполагать, чтоnew int[] {1}.SequenceEquals(null) == false
Сара
30
Также для массивов (и кортежей) вы можете использовать новые интерфейсы из .NET 4.0: IStructuralComparable и IStructuralEquatable . Используя их, вы можете не только проверить равенство массивов, но и сравнить их.
staticclassStructuralExtensions{publicstaticboolStructuralEquals<T>(this T a, T b)where T :IStructuralEquatable{return a.Equals(b,StructuralComparisons.StructuralEqualityComparer);}publicstaticintStructuralCompare<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));// FalseConsole.WriteLine(a.StructuralEquals(b));// True}{var a =new[]{1,3,3};var b =new[]{1,2,3};Console.WriteLine(a.StructuralCompare(b));// 1}
Простите, это должно быть 1 или 0 в a.StructuralCompare(b)?
Мафу
В массивах с типами больших значений при их использовании наблюдается снижение производительности, поскольку их текущая реализация будет помечать каждое значение для сравнения.
Фредерик
18
Для .NET 4.0 и выше вы можете сравнивать элементы в массиве или кортежах, используя тип StructuralComparisons :
Редактировать: говорил слишком рано. Могу ли я сделать StructualEqualityCompare с IStructuralComparable? Я хочу вызвать CompareTo с двумя массивами объектов, чтобы выяснить, какой из них «первый». Я попытался IStructuralComparable se1 = a1; Console.WriteLine (se1.CompareTo (a2, StructuralComparisons.StructuralEqualityComparer)); Получение: невозможно преобразовать из 'System.Collections.IEqualityComparer' в 'System.Collections.IComparer'
SequenceEqual вернет 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);
вы получите разные результаты.
В моем случае у меня есть локальная копия массива и я хочу проверить, было ли что-либо удалено из исходного массива, поэтому я использую этот метод.
Массивы, содержащие одинаковые значения в разном порядке, просто НЕ РАВНЫ. Вы что, 'Demetriou' == 'uoirtemeD'?
edc65
Это зависит. Если вы используете массивы в качестве неупорядоченных коллекций и вам нужно проверять только то, что они содержат одинаковые элементы (например, значения из базы данных в списке конфигурации), то это самый простой способ, который я нашел. Если порядок имеет значение (например, строка), то вы бы использовали SequenceEqual.
Армандо
11
Для юнит-тестов вы можете использовать CollectionAssert.AreEqualвместо Assert.AreEqual.
Это было полезно для меня, но если a1 = { 1, 1 }и a2 = { 1, 2 }, то первый тест возвращает неправильный результат. Заявление о возврате должно бытьreturn array1.Count() == array2.Count() && !array1.Except(array2).Any() && !array2.Except(array1).Any();
Это решение LINQ работает, но не уверен, как оно сравнивается по производительности с SequenceEquals. Но он обрабатывает разные длины массивов, и .All завершится для первого элемента, который не равен, без итерации по всему массиву.
Он не обрабатывает массивы разной длины (происходит сбой), nullмассивы (также происходит сбой) и делает что-то еще, кроме того, что запросил OP. Он только просил знать равенство, не считая, сколько предметов отличаются или совпадают.
Фредерик
0
Если предположить, что равенство массивов означает, что оба массива имеют одинаковые элементы с одинаковыми индексами, то есть SequenceEqualответ и IStructuralEquatableответ .
Но у обоих есть недостатки, с точки зрения производительности.
SequenceEqual текущая реализация не будет ярлыком, когда массивы имеют разную длину, и поэтому может полностью перечислить один из них, сравнивая каждый из его элементов.
IStructuralEquatableне является общим и может вызывать упаковку каждого сравниваемого значения. Более того, он не очень прост в использовании и уже требует кодирования некоторых вспомогательных методов, скрывая его.
С точки зрения производительности может быть лучше использовать что-то вроде:
boolArrayEquals<T>(T[] first, T[] second){if(first == second)returntrue;if(first ==null|| second ==null)returnfalse;if(first.Length!= second.Length)returnfalse;for(var i =0; i < first.Length; i++){if(first[i]!= second[i])returnfalse;}returntrue;}
Но, конечно, это не какой-то «магический способ» проверки равенства массивов.
Так что в настоящее время нет, на самом деле нет эквивалента Java Arrays.equals()в .Net.
Ответы:
Вы могли бы использовать
Enumerable.SequenceEqual
. Это работает для любыхIEnumerable<T>
, а не только массивов.источник
SequenceEqual
не может быть хорошим выбором с точки зрения производительности, потому что его текущая реализация может полностью перечислять один из его источников, если они отличаются только длиной. С массивами мы могли быLength
сначала проверить равенство, чтобы избежать перечисления массивов разной длины, чтобы в конечном итоге дать результатfalse
.Используйте
Enumerable.SequenceEqual
в LINQ .источник
new int[] {1}.SequenceEquals(null) == false
Также для массивов (и кортежей) вы можете использовать новые интерфейсы из .NET 4.0: IStructuralComparable и IStructuralEquatable . Используя их, вы можете не только проверить равенство массивов, но и сравнить их.
источник
a.StructuralCompare(b)
?Для .NET 4.0 и выше вы можете сравнивать элементы в массиве или кортежах, используя тип StructuralComparisons :
источник
SequenceEqual
вернет true, только если выполнены два условия.Если вы только хотите проверить, содержат ли они одинаковые элементы, независимо от их порядка, и ваша проблема имеет тип
Вы можете использовать метод расширения LINQ,
Enumerable.Except
а затем проверить, имеет ли результат какое-либо значение. Вот примерА также с помощью этого вы автоматически получаете различные предметы. Две птицы с одним камнем.
Имейте в виду, если вы выполняете свой код, как это
вы получите разные результаты.
В моем случае у меня есть локальная копия массива и я хочу проверить, было ли что-либо удалено из исходного массива, поэтому я использую этот метод.
источник
SequenceEqual
.Для юнит-тестов вы можете использовать
CollectionAssert.AreEqual
вместоAssert.AreEqual
.Это, наверное, самый простой способ.
источник
Если вы хотите корректно обрабатывать
null
вводимые данные и игнорировать порядок элементов, попробуйте следующее решение:Тестовый код выглядит так:
источник
a1 = { 1, 1 }
иa2 = { 1, 2 }
, то первый тест возвращает неправильный результат. Заявление о возврате должно бытьreturn array1.Count() == array2.Count() && !array1.Except(array2).Any() && !array2.Except(array1).Any();
Для некоторых приложений может быть лучше:
источник
Это решение LINQ работает, но не уверен, как оно сравнивается по производительности с SequenceEquals. Но он обрабатывает разные длины массивов, и .All завершится для первого элемента, который не равен, без итерации по всему массиву.
источник
поэлементно сравнивать? что о
Замените условие (a == b) тем, что вы хотите сравнить в a и b.
(это объединяет два примера из примеров Linq разработчика MSDN )
источник
true
) иnull
массивы (вылетает).Я делал это в визуальных студиях, и это работало отлично; Сравнение индекса массива по индексу с коротким кодом.
выходной будет; Соответствующие номера 7 Не соответствующие номера 3
источник
null
массивы (также происходит сбой) и делает что-то еще, кроме того, что запросил OP. Он только просил знать равенство, не считая, сколько предметов отличаются или совпадают.Если предположить, что равенство массивов означает, что оба массива имеют одинаковые элементы с одинаковыми индексами, то есть
SequenceEqual
ответ иIStructuralEquatable
ответ .Но у обоих есть недостатки, с точки зрения производительности.
SequenceEqual
текущая реализация не будет ярлыком, когда массивы имеют разную длину, и поэтому может полностью перечислить один из них, сравнивая каждый из его элементов.IStructuralEquatable
не является общим и может вызывать упаковку каждого сравниваемого значения. Более того, он не очень прост в использовании и уже требует кодирования некоторых вспомогательных методов, скрывая его.С точки зрения производительности может быть лучше использовать что-то вроде:
Но, конечно, это не какой-то «магический способ» проверки равенства массивов.
Так что в настоящее время нет, на самом деле нет эквивалента Java
Arrays.equals()
в .Net.источник
null
. Какова ваша позиция?