Thalecress
Thalecress

Reputation: 3451

How can I combine an IEnumerable(Of IEnumerable) using LINQ?

I've got a List(Of HashSet(Of String)). Is there a clear, one-line LINQ way to get a single HashSet(Of String) containing all the strings in the list entry values?

For example, from the 3 hashsets {"A"}, {"A","B","C"}, and {"B","C","D"} I'd like a single hashset {"A","B","C","D"}.

I'm pretty sure I can do something with .Aggregate() or .Accumulate().

C# or VB.NET explanations are equally helpful.

Upvotes: 4

Views: 1412

Answers (3)

Zack Butcher
Zack Butcher

Reputation: 1106

SelectMany does exactly this. At a high level (omitting the generics and simplifying a bit), SelectMany is implemented like:

static IEnumerable SelectMany(this source, Func selector)
{
    IEnumerable results;
    foreach (var item in source)
    {
        foreach (var result in selector(item))
        {
            results.add(result);
        }
    }
    return results;
}

The above code is not actually accurate; instead it uses a yield return to perform the select lazily and uses no intermediate collection results. Finally, the full signature is actually public static IEnumerable<TResult> SelectMany<TSource, TResult>( this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector), but the only important piece to understand is that selector returns a collection. If you have a collection of collections then using the identity function x => x does exactly that.

So, it flattens collections of collections into a single collection. Using the identity function x => x as the selector means that the elements of the inner collections are unchanged. So, as a few others have posted, the final answer would be:

var newSet = new HashSet(setOfSets.SelectMany(element => element));

Upvotes: 2

Agop Dogramadzhiyan
Agop Dogramadzhiyan

Reputation: 96

You can try using UnionWith method of HashSet. It will be something like this:

var result = myListOfHashSets.Aggregate(new HashSet<string>(), (x, y) => { x.UnionWith(y); return x; });

Upvotes: 1

p.s.w.g
p.s.w.g

Reputation: 149078

You can just use SelectMany. In C#:

var newHashSet = new HashSet<string>(myListOfHashSets.SelectMany(x => x));

And in VB.NET:

Dim newHashSet As New HashSet(Of String)(myListOfHashSets.SelectMany(Function (x) x))

Upvotes: 10

Related Questions