Самый простой способ сравнить массивы в C # - PullRequest
139 голосов
/ 13 июля 2010

В Java Arrays.equals () позволяет легко сравнивать содержимое двух основных массивов (доступны перегрузки для всех основных типов).C #?Есть ли «волшебный» способ сравнения содержимого двух массивов в C #?

Ответы [ 12 ]

211 голосов
/ 13 июля 2010

Вы можете использовать SequenceEqual . Это работает для любых IEnumerable<T>, а не только для массивов.

53 голосов
/ 13 июля 2010

Использование SequenceEqual in 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
27 голосов
/ 13 июля 2010

Также для массивов (и кортежей) вы можете использовать новые интерфейсы из .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
}
17 голосов
/ 07 ноября 2014

Для .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)); 
12 голосов
/ 12 февраля 2016

SequenceEqual вернет true, только если выполнены два условия.

  1. Они содержат одинаковые элементы.
  2. Элементы расположены в одинаковом порядке.

Если вы хотите проверить, содержат ли они одинаковые элементы независимо от их порядка, и ваша проблема имеет тип

Содержит ли 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);

, вы получите разные результаты.

В моем случае у меня естьлокальная копия массива и хочу проверить, было ли что-либо удалено из исходного массива, поэтому я использую этот метод.

7 голосов
/ 01 февраля 2017

Для модульных тестов вы можете использовать CollectionAssert.AreEqual вместо Assert.AreEqual.

Это, наверное, самый простой способ.

4 голосов
/ 28 июня 2017

Если вы хотите изящно обрабатывать 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.
    }
}
2 голосов
/ 20 июля 2017

Для некоторых приложений может быть лучше:

string.Join(",", arr1) == string.Join(",", arr2)
0 голосов
/ 27 июня 2019

Это решение 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)
            );
0 голосов
/ 14 февраля 2019

Предполагая, что равенство массивов означает, что оба массива имеют одинаковые элементы с одинаковыми индексами, существует ответ 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...