Как сравнить значения в двух списках?

У меня есть два списка

List 01 => { A, B, C, D, E }
List 02 => { F, F, F, F, E }

Мне нужно проверить, существует ли один элемент из List 02 в List 01, поэтому следующее должно быть false.

List 01 => { A, B, C, D, E }
List 02 => { F, F, F, F, F } // no element matches

И здесь это должно быть true.

List 01 => { A, B, C, D, E }
List 02 => { F, F, F, F, B } // last element matches

Как я могу проверить это?

Меня беспокоит производительность.

Ответ 1

Есть несколько способов сделать это:

Пересечение

Если результат пересечения приводит к 1 или более элементам, это означает, что хотя бы один равный элемент.

var result = list01.Intersect(list02);
bool hasElement = result.Any();

Я рекомендую использовать этот метод.

В качестве второго параметра можно передать IEqualityComparer<T>, если вам нужно сравнить сложные типы.

За исключением

Если результат исключения имеет общее количество элементов в целом, это означает, что существует хотя бы один равный элемент.

var result = list01.Except(list02);
bool hasElement = result.Count() != list01.Count;

В качестве второго параметра можно передать IEqualityComparer<T>, если вам нужно сравнить сложные типы.

Любые

Если какой-либо элемент в списке01 равен любому элементу в списке02, это означает, что существует хотя бы один равный элемент.

bool hasElement = list01.Any(e => list02.Any(o => o == e));

Любые e IndexOf

Если какой-либо элемент в списке01 найден в списке02, это означает, что в лизинге есть один равный элемент.

bool hasElement = list01.Any(e => list02.IndexOf(e) != -1);

Недостатком IndexOf является то, что вы не можете передать IEqualityComparer<T>, вместо этого он всегда будет использовать значение по умолчанию, EqualityComparer<T>.Default.


Производительность

В большом списке list01.Any(e => list02.Any(o => o == e)) будет иметь хорошую производительность , только если одно из значений от начала первого в списке, содержащемся во втором списке. В противном случае производительность будет ужасной, так как итерации последовательны.

В тесте производительности я получил следующие результаты:

Списки по 5 элементов каждый, проверены 10000000 раз.

Intersect     : 00:00:02.9260135
Except        : 00:00:03.4404527
AnyAny        : 00:00:06.5709693
AnyIndexOf    : 00:00:01.9882278

Списки с 100000 элементами каждый, проверены 500 раз. Последний элемент списка02 равен третьему элементу в списке01:

Intersect     : 00:00:02.4397784
Except        : 00:00:04.2595364
AnyAny        : 00:00:02.9761128
AnyIndexOf    : 00:00:00.0919344

Списки с 100000 элементами каждый, проверены 500 раз. Последний элемент списка02 равен последнему элементу в списке01.

Intersect     : 00:00:02.4927969
Except        : 00:00:04.2668677
AnyAny        : more than a minute and I dropped the test
AnyIndexOf    : more than a minute and I dropped the test

Ответ 2

list1.Intersect(list2).Any()

Это будет наиболее эффективным, так как он использует HashSets.

Ответ 3

Enumerable.Except и Enumerable.Intersect.

Ответ 4

попробуйте

list1.Any(e => list2.Contains(e));

например.

var list1 = new List<string> { "A", "B", "C", "D" };
var list2 = new List<string> { "F", "F", "F" };

list1.Any(e => list2.Contains(e)); // returns false

var list3 = new List<string> { "F", "F", "D" };

list1.Any(e => list3.Contains(e)); // returns true

UPDATE:, как указывает leppie, использование Intersect будет более эффективным, esp, если списки большие.