Хобрук: Ваш путь к мастерству в программировании

Использование Linq Except с двумя списками массивов int

Можно ли использовать, кроме двух списков массивов int, например:

List<int[]> a = new List<int[]>(){ new int[]{3,4,5}, new int[]{7,8,9}, new int[]{10,11,12}  };

List<int[]> b = new List<int[]>(){ new int[]{6,7,9}, new int[]{3,4,5}, new int[]{10,41,12}  };

var c = a.Except(b);

и ожидая, что {3,4,5} отсутствует в перечислимом c? Конечно, я пробовал, и этот не работает. Есть ли решение столь же эффективное, как Except? Или еще лучше, быстрее?

27.03.2016

Ответы:


1

В .NET массивы равны друг другу только в том случае, если они являются одним и тем же объектом массива. Таким образом, два разных массива с одинаковым содержимым не считаются равными:

int[] x = new int[] { 1, 2 };
int[] y = new int[] { 1, 2 };
Console.WriteLine(x == y); // false

Чтобы проверить равенство на основе содержимого, вы можете использовать Enumerable.SequenceEqual :

Console.WriteLine(x.SequenceEqual(y)); // true

Конечно, это не поможет вам напрямую при попытке использовать Enumerable.Except, поскольку по умолчанию будет использоваться компаратор равенства по умолчанию, который проверяет только равенство (и поскольку каждый массив не равен любому другому массиву, кроме самого себя…).

Таким образом, решением будет использовать другую перегрузку и предоставить пользовательский IEqualityComparer, который сравнивает массивы на основе их содержимого.

public class IntArrayEqualityComparer : IEqualityComparer<int[]>
{
    public bool Equals(int[] a, int[] b)
    {
        return a.SequenceEqual(b);
    }

    public int GetHashCode(int[] a)
    {
        return a.Sum();
    }
}

К сожалению, просто передать полномочия SequenceEqual недостаточно. Мы также должны предоставить реализацию GetHashCode, чтобы это работало. В качестве простого решения мы можем использовать здесь сумму чисел в массиве. Обычно мы хотели бы предоставить сильную хеш-функцию, которая много говорит о содержимом, но поскольку мы используем эту хеш-функцию только для вызова Except, мы можем использовать здесь что-то простое. (Вообще, мы также хотели бы избежать создания хеш-значения из изменяемого объекта)

И при использовании этого компаратора равенства мы правильно отфильтровываем повторяющиеся массивы:

var c = a.Except(b, new IntArrayEqualityComparer());
27.03.2016
  • Спасибо за объяснение и за рабочее решение! 27.03.2016

  • 2

    Это связано с тем, что EqualityComparer по умолчанию для массива int возвращает false для массивов с одинаковыми значениями:

    int[] a1 = { 1, 2, 3 };
    int[] a2 = { 1, 2, 3 };
    var ec = EqualityComparer<int[]>.Default;
    Console.WriteLine(ec.Equals(a1, a2));//result is false
    

    Вы можете исправить это, реализовав свой собственный EqualityComparer и передав его экземпляр методу Except (см. документацию).

    Вы также можете прочитать о сравнении массивов в C# здесь.

    27.03.2016
  • Спасибо за подсказки 27.03.2016
  • Новые материалы

    Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
    каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

    Как настроить Selenium в проекте Angular
    Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..