Проверьте, равны ли два списка - программирование
Подтвердить что ты не робот

Проверьте, равны ли два списка

У меня есть класс следующим образом:

public class Tag {
    public Int32 Id { get; set; }
    public String Name { get; set; }
}

И у меня есть два списка тегов:

List<Tag> tags1;
List<Tag> tags2;

Я использовал LINQ, чтобы получить идентификаторы каждого списка тэгов. И затем:

List<Int32> ids1 = new List<Int32> { 1, 2, 3, 4 };
List<Int32> ids2 = new List<Int32> { 1, 2, 3, 4 };
List<Int32> ids3 = new List<Int32> { 2, 1, 3, 4 };
List<Int32> ids4 = new List<Int32> { 1, 2, 3, 5 };
List<Int32> ids5 = new List<Int32> { 1, 1, 3, 4 };

ids1 должно быть равно ids2 и ids3... Оба имеют одинаковые числа.

ids1 не должен быть равным ids4 и ids5...

Я попробовал следующее:

var a = ints1.Equals(ints2);
var b = ints1.Equals(ints3);

Но оба дают мне ложь.

Каков самый быстрый способ проверить, совпадают ли списки тегов?

UPDATE

Я ищу POSTS, которые TAGS точно такие же, как TAGS в книге.

IRepository repository = new Repository(new Context());

IList<Tags> tags = new List<Tag> { new Tag { Id = 1 }, new Tag { Id = 2 } };

Book book = new Book { Tags = new List<Tag> { new Tag { Id = 1 }, new Tag { Id = 2 } } };

var posts = repository
  .Include<Post>(x => x.Tags)
  .Where(x => new HashSet<Int32>(tags.Select(y => y.Id)).SetEquals(book.Tags.Select(y => y.Id)))
  .ToList();

Я использую Entity Framework, и я получаю сообщение об ошибке:

Исключение типа "System.NotSupportedException" произошло в mscorlib.dll, но не было обработано в коде пользователя

Дополнительная информация: LINQ to Entities не распознает метод 'Boolean SetEquals (System.Collections.Generic.IEnumerable`1 [System.Int32])', и этот метод не может быть переведен в выражение хранилища.

Как это решить?

4b9b3361

Ответ 1

Используйте SequenceEqual, чтобы проверить равенство последовательности, потому что метод Equals проверяет ссылочное равенство.

var a = ints1.SequenceEqual(ints2);

Или, если вам не нужен порядок элементов, используйте метод Enumerable.All:

var a = ints1.All(ints2.Contains);

Вторая версия также требует другой проверки для Count, потому что она вернет true, даже если ints2 содержит больше элементов, чем ints1. Поэтому более правильная версия будет примерно такой:

var a = ints1.All(ints2.Contains) && ints1.Count == ints2.Count;

Чтобы проверить неравенство, просто отмените результат метода All:

var a = !ints1.All(ints5.Contains)

Ответ 2

List<T> равенство не проверяет их поэтапно. Вы можете использовать метод LINQ SequenceEqual для этого:

var a = ints1.SequenceEqual(ints2);

Чтобы игнорировать порядок, используйте SetEquals:

var a = new HashSet<int>(ints1).SetEquals(ints2);

Это должно работать, потому что вы сравниваете последовательности идентификаторов, которые не содержат дубликатов. Если это так, и вам нужно учитывать дубликаты, способ сделать это в линейном времени состоит в том, чтобы составить хеш-словарь для подсчета, добавить один для каждого элемента первой последовательности, вычесть его для каждого элемента второго последовательность и проверить, являются ли результирующие подсчеты нулями:

var counts = ints1
    .GroupBy(v => v)
    .ToDictionary(g => g.Key, g => g.Count());
var ok = true;
foreach (var n in ints2) {
    int c;
    if (counts.TryGetValue(n, out c)) {
        counts[n] = c-1;
    } else {
        ok = false;
        break;
    }
}
var res = ok && counts.Values.All(c => c == 0);

Наконец, если вы в порядке с решением O(N*LogN), вы можете отсортировать две последовательности и сравнить их для равенства с помощью SequenceEqual.

Ответ 3

Enumerable.SequenceEqual(FirstList.OrderBy(fElement => fElement), 
                         SecondList.OrderBy(sElement => sElement))