13

我以为我明白Intersect了,但事实证明我错了。

 List<int> list1 = new List<int>() { 1, 2, 3, 2, 3};
 List<int> list2 = new List<int>() { 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<int>();
 list3.AddRange(list1.Where(I => intersected.Contains(I)));
 list3.AddRange(list2.Where(I => intersected.Contains(I)));

LINQ 中是否有更简单的方法来实现这一点?

我确实需要声明,我不在乎给出结果的顺序。

2,2,2,3,3,3,3 也完全可以。

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

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

4

4 回答 4

19

让我们看看我们是否可以准确地描述您想要的内容。如果我错了,请纠正我。您想要:列表 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();

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

于 2010-02-01T21:22:30.043 回答
1
var set = new HashSet(list1.Intersect(list2));
return list1.Concat(list2).Where(i=>set.Contains(i));
于 2010-02-01T22:00:56.023 回答
0

也许这会有所帮助:https ://gist.github.com/mladenb/b76bcbc4063f138289243fb06d099dda

原始的 except/Intersect 返回一个唯一项的集合,即使它们的合同没有这样说明(例如,这些方法的返回值不是 HashSet/Set,而是 IEnumerable),这可能是一个差的结果设计决策。相反,我们可以使用更直观的实现,它从第一个枚举中返回尽可能多的相同元素,而不仅仅是一个唯一的(使用 Set.Contains)。

此外,还添加了映射功能,以帮助交叉/排除不同类型的集合。

如果您不需要交叉/排除不同类型的集合,只需检查 Intersect/Except 的源代码并将迭代第一个枚举的部分更改为使用 Set.Contains 而不是 Set.Add/Set.Remove。

于 2019-04-04T07:37:55.190 回答
-1

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

IEnumerable<T> Intersect2<T>(this IEnumerable<T> left, IEnumerable<T> 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;
    }
  }
}
于 2010-02-01T21:19:56.427 回答