我应该如何比较两个列表中的值?

时间:2021-05-05 11:29:28

I have two lists

我有两个清单

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

I need to check if one element of List 02 exists in List 01, so the following should be false.

我需要检查List 01中是否存在List 02的一个元素,因此以下内容应为false。

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

And here it should be true.

这应该是真的。

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

How can I check that?

我怎么检查?

I'm concerned about performance as well.

我也很关心表现。

4 个解决方案

#1


13  

list1.Intersect(list2).Any()

This will be most performant as it uses HashSets.

这将是最有效的,因为它使用HashSet。

#2


6  

There are a few different ways to do it:

有几种不同的方法可以做到:

Intersect

If the result of the intersection result in 1 or more elements, it means that at least one equal element.

如果交集的结果导致1个或多个元素,则表示至少有一个相等的元素。

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

I recommend the use of this method.

我建议使用这种方法。

It is possible to pass a IEqualityComparer<T> as the second parameter in case you need to compare complex types.

如果需要比较复杂类型,可以将IEqualityComparer 作为第二个参数传递。

Except

If the result of a except has different amount of elements in total, it means that there is at least one equal element.

如果一个except的结果总共有不同数量的元素,则意味着至少有一个相等的元素。

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

It is possible to pass a IEqualityComparer<T> as the second parameter in case you need to compare complex types.

如果需要比较复杂类型,可以将IEqualityComparer 作为第二个参数传递。

Any

If any element in the list01 is equal any element in the list02, it means that there is at least one equal element.

如果list01中的任何元素与list02中的任何元素相等,则表示至少有一个相等的元素。

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

Any e IndexOf

If any element in the list01 is found in list02, it means that there is at lease one equal element.

如果在list02中找到list01中的任何元素,则意味着至少有一个相等的元素。

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

The disadvantage of IndexOf is that you can't pass a IEqualityComparer<T>, instead it will always use the default, EqualityComparer<T>.Default.

IndexOf的缺点是您无法传递IEqualityComparer ,而是始终使用默认的EqualityComparer .Default。


Performance

In a big list, list01.Any(e => list02.Any(o => o == e)) will have a good performance only if one of the values from the beginning of the first in contained in the second list. Otherwise the performance will be awful, as the iterations are sequential.

在一个大的列表中,list01.Any(e => list02.Any(o => o == e))只有在第二个列表中包含的第一个开头的值之一时才会有良好的性能。否则性能会很糟糕,因为迭代是连续的。

In a performance test I got the following results:

在性能测试中,我得到了以下结果:

Lists with 5 elements each, tested 10000000 times.

每个列表包含5个元素,测试10000000次。

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

Lists with 100000 elements each, tested 500 times. The last element of list02 is equal to the third element in list01:

每个列有100000个元素,测试500次。 list02的最后一个元素等于list01中的第三个元素:

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

Lists with 100000 elements each, tested 500 times. The last element of list02 is equal to the last element in list01.

每个列有100000个元素,测试500次。 list02的最后一个元素等于list01中的最后一个元素。

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

#3


5  

Enumerable.Except & Enumerable.Intersect.

Enumerable.Except&Enumerable.Intersect。

#4


3  

try

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

e.g.

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: as leppie points out, using Intersect will be more performant, esp if the lists are large.

更新:正如leppie指出的那样,使用Intersect将更具性能,尤其是如果列表很大。

#1


13  

list1.Intersect(list2).Any()

This will be most performant as it uses HashSets.

这将是最有效的,因为它使用HashSet。

#2


6  

There are a few different ways to do it:

有几种不同的方法可以做到:

Intersect

If the result of the intersection result in 1 or more elements, it means that at least one equal element.

如果交集的结果导致1个或多个元素,则表示至少有一个相等的元素。

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

I recommend the use of this method.

我建议使用这种方法。

It is possible to pass a IEqualityComparer<T> as the second parameter in case you need to compare complex types.

如果需要比较复杂类型,可以将IEqualityComparer 作为第二个参数传递。

Except

If the result of a except has different amount of elements in total, it means that there is at least one equal element.

如果一个except的结果总共有不同数量的元素,则意味着至少有一个相等的元素。

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

It is possible to pass a IEqualityComparer<T> as the second parameter in case you need to compare complex types.

如果需要比较复杂类型,可以将IEqualityComparer 作为第二个参数传递。

Any

If any element in the list01 is equal any element in the list02, it means that there is at least one equal element.

如果list01中的任何元素与list02中的任何元素相等,则表示至少有一个相等的元素。

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

Any e IndexOf

If any element in the list01 is found in list02, it means that there is at lease one equal element.

如果在list02中找到list01中的任何元素,则意味着至少有一个相等的元素。

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

The disadvantage of IndexOf is that you can't pass a IEqualityComparer<T>, instead it will always use the default, EqualityComparer<T>.Default.

IndexOf的缺点是您无法传递IEqualityComparer ,而是始终使用默认的EqualityComparer .Default。


Performance

In a big list, list01.Any(e => list02.Any(o => o == e)) will have a good performance only if one of the values from the beginning of the first in contained in the second list. Otherwise the performance will be awful, as the iterations are sequential.

在一个大的列表中,list01.Any(e => list02.Any(o => o == e))只有在第二个列表中包含的第一个开头的值之一时才会有良好的性能。否则性能会很糟糕,因为迭代是连续的。

In a performance test I got the following results:

在性能测试中,我得到了以下结果:

Lists with 5 elements each, tested 10000000 times.

每个列表包含5个元素,测试10000000次。

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

Lists with 100000 elements each, tested 500 times. The last element of list02 is equal to the third element in list01:

每个列有100000个元素,测试500次。 list02的最后一个元素等于list01中的第三个元素:

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

Lists with 100000 elements each, tested 500 times. The last element of list02 is equal to the last element in list01.

每个列有100000个元素,测试500次。 list02的最后一个元素等于list01中的最后一个元素。

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

#3


5  

Enumerable.Except & Enumerable.Intersect.

Enumerable.Except&Enumerable.Intersect。

#4


3  

try

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

e.g.

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: as leppie points out, using Intersect will be more performant, esp if the lists are large.

更新:正如leppie指出的那样,使用Intersect将更具性能,尤其是如果列表很大。