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

时间:2010-08-23 13:00:30

标签: c# .net linq

我有两个列表

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

我该怎么检查?

我也关注性能

4 个答案:

答案 0 :(得分:13)

list1.Intersect(list2).Any()

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

答案 1 :(得分:6)

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

Intersect

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

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

我建议使用这种方法。

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

Except

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

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

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

Any

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

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

Any e IndexOf

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

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次。 list02的最后一个元素等于list01中的第三个元素:

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

列出每个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

答案 2 :(得分:5)

Enumerable.Except&amp; Enumerable.Intersect

答案 3 :(得分:3)

尝试

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

更新:正如leppie指出的那样,使用Intersect会更高效,特别是如果列表很大。