C#LINQ集合的“内部联接”

时间:2017-02-06 12:41:41

标签: c# .net linq collections lambda

基本上我有一个IEnumerable<IEnumerable<T>>对象,我想从IEnumerable<T>对象中存在所有中的对象。

我正在尝试编写尽可能优雅的代码,我想知道是否有一些LINQ技巧,最好是单行。如果它可以提供帮助,则IEnumerable都是ISet

目前我正在使用类似下面的代码:

// Some starting data - collection of collections
HashSet<HashSet<ulong>> data = new HashSet<HashSet<ulong>> { new HashSet<ulong> { 1, 2, 3 }, new HashSet<ulong> { 2, 3, 4 }, new HashSet<ulong> { 3, 4, 5 } };

// Flatten collection of collections into a single collection with unique elements
HashSet<ulong> result = new HashSet<ulong>(data.SelectMany(set => set));

// Remove from it all elements that are missing from 1 or more initial collections
result.RemoveWhere(number => data.Any(set => !set.Contains(number)));

// The result is: HashSet<ulong> { 3 }

它有效,但我在这里做了几件事,比如枚举初始集合两次,创建半就绪结果并迭代+从中移除元素。

我很确定应该有一个选项可以一次性使用LINQ,我基本上都在寻找类似的东西:

HashSet<HashSet<ulong>> data = new HashSet<HashSet<ulong>> { new HashSet<ulong> { 1, 2, 3 }, new HashSet<ulong> { 2, 3, 4 }, new HashSet<ulong> { 3, 4, 5 } };elements
HashSet<ulong> result = data.LinqInnerJoinMagic(set => set);

C#中是否存在类似的内容?也许作为一种扩展方法?我努力使用LINQ Join(),但我无法找到如何使它适应我的例子,我很感激有用的手,很可能答案是如此简单,我不能真的找到它。

提前谢谢!

3 个答案:

答案 0 :(得分:2)

您可以使用HashSet<T>.IntersectWith

Card
  

修改当前... public Deck(){ for(int i = 0; i < CARD_SET; i++){ Card card = new Card(); if( i >= 0 && i < NUM_FACE) { card.setSuite("club"); card.setFace(i + 1); ... 对象以仅包含其中的元素   存在于该对象和指定的集合中。

答案 1 :(得分:1)

与intersect结合使用的聚合将为您提供所有集合中存在的公共元素。

var orderedData = data.ToList();
var commonSet = orderedData.Skip(1).Aggregate((IEnumerable<ulong>)(orderedData.First()), (c, n) => c.Intersect(n));

答案 2 :(得分:1)

试试这个:

var result = new HashSet<ulong>(
      data.SelectMany(x => x).Where(x => data.All(z => z.Contains(x)))
);

请参阅MSDN