简体   繁体   English

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

[英]C# LINQ “inner join” of collections

Basically I have a IEnumerable<IEnumerable<T>> object and I want to get from it IEnumerable<T> of objects that exist in all of the collections. 基本上,我有一个IEnumerable<IEnumerable<T>>对象,并且我想从中获取所有集合中存在的对象的IEnumerable<T>

I'm trying to code that as elegant as possible, and I'm wondering if there is some LINQ trick of doing that, preferably one-liner. 我正在尝试编写尽可能优雅的代码,并且想知道这样做是否有一些LINQ技巧,最好是单行代码。 If it can help, both IEnumerable s are ISet . 如果有帮助,则两个IEnumerable都为ISet

Currently I'm using a code similar to below: 目前,我正在使用类似于以下代码:

// 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 }

It works, but I'm doing several things here such as enumerating initial collection twice, creating a half-ready result and iterating + removing elements from it. 它可以工作,但是我在这里做了几件事情,例如两次枚举初始集合,创建半就绪结果以及迭代+从中删除元素。

I'm pretty sure there should be an option to do that in one-go with LINQ, I'm basically looking for something like: 我很确定应该有一个选项可以通过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);

Does something like this exist in C#? C#中是否存在类似的东西? Maybe as an extension method? 也许作为扩展方法? I tried hard to make use of LINQ Join() but I couldn't find out how to adapt it to my example, I'd appreciate a helpful hand, it's very likely that the answer is so simple that I can't really find it. 我尽力使用LINQ Join()但是我找不到如何使它适应我的示例的方法,我会很乐于助人,很可能答案很简单,以至于我找不到真正的答案。它。

Thank you in advance! 先感谢您!

You can use HashSet<T>.IntersectWith : 您可以使用HashSet<T>.IntersectWith

HashSet<ulong> result = data.First();
foreach (HashSet<ulong> set in data.Skip(1))
    result.IntersectWith(set);

Modifies the current HashSet<T> object to contain only elements that are present in that object and in the specified collection. 修改当前HashSet<T>对象,使其仅包含该对象和指定集合中存在的元素。

Aggregate combined with intersect will get you the common elements that exist in all sets. 集合与相交相结合将为您提供所有集合中存在的公共元素。

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

Try this: 尝试这个:

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

See MSDN 参见MSDN

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM