查找所有相交数据,而不仅仅是唯一值

我以为我理解了Intersect ,但事实certificate我错了。

  List list1 = new List() { 1, 2, 3, 2, 3}; List list2 = new List() { 2, 3, 4, 3, 4}; list1.Intersect(list2) => 2,3 //But what I want is: // => 2,3,2,3,2,3,3 

我可以想象一下:

  var intersected = list1.Intersect(list2); var list3 = new List(); list3.AddRange(list1.Where(I => intersected.Contains(I))); list3.AddRange(list2.Where(I => intersected.Contains(I))); 

在LINQ中有更简单的方法来实现这一目标吗?

我需要说明我不关心结果的顺序。

2,2,2,3,3,3,3也可以。

问题是我在一个非常大的集合上使用它,所以我需要效率。

我们谈论的是对象,而不是整体。 这只是一个简单的例子,但我意识到这可以有所作为。

让我们看看我们是否可以精确地描述你想要的东西。 如果我错了,请纠正我。 你想要:列表1的所有元素,按顺序,也出现在列表2中,然后是列表2的所有元素,按顺序,也出现在列表1中。是吗?

似乎很简单。

 return list1.Where(x=>list2.Contains(x)) .Concat(list2.Where(y=>list1.Contains(y))) .ToList(); 

请注意,这对大型列表无效 。 如果列表每个都有一千个项目,那么这将进行几百万次比较。 如果您处于这种情况,那么您希望使用更有效的数据结构来测试成员身份:

 list1set = new HashSet(list1); list2set = new HashSet(list2); return list1.Where(x=>list2set.Contains(x)) .Concat(list2.Where(y=>list1set.Contains(y))) .ToList(); 

它只进行了几千次比较,但可能会使用更多的内存。

 var set = new HashSet(list1.Intersect(list2)); return list1.Concat(list2).Where(i=>set.Contains(i)); 

我不相信内置API可以实现这一点。 但您可以使用以下内容来获得您正在寻找的结果。

 IEnumerable Intersect2(this IEnumerable left, IEnumerable right) { var map = left.ToDictionary(x => x, y => false); foreach ( var item in right ) { if (map.ContainsKey(item) ) { map[item] = true; } } foreach ( var cur in left.Concat(right) ) { if ( map.ContainsKey(cur) ) { yield return cur; } } }