Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant way to combine multiple collections of elements?

People also ask

How to combine two collections in Java?

If you need to combine more than two Streams, you can invoke the concat() method again from within the original invocation: Stream<String> combinedStream = Stream. concat( Stream. concat(collectionA.

How do I combine Iterables?

Concatenate Iterables using concat Method The Iterables class provides concat method that accepts n number of Iterable instances and returns a new Iterable instance having all elements concatenated. Note that this method creates a new instance; hence we can pass Immutable Lists.


I think you might be looking for LINQ's .Concat()?

var combined = foo.Concat(bar).Concat(foobar).Concat(...);

Alternatively, .Union() will remove duplicate elements.


To me Concat as an extension method is not very elegant in my code when I have multiple large sequences to concat. This is merely a codde indentation/formatting problem and something very personal.

Sure it looks good like this:

var list = list1.Concat(list2).Concat(list3);

Not so readable when it reads like:

var list = list1.Select(x = > x)
   .Concat(list2.Where(x => true)
   .Concat(list3.OrderBy(x => x));

Or when it looks like:

return Normalize(list1, a, b)
    .Concat(Normalize(list2, b, c))
       .Concat(Normalize(list3, c, d));

or whatever your preferred formatting is. Things get worse with more complex concats. The reason for my sort of cognitive dissonance with the above style is that the first sequence lie outside of the Concat method whereas the subsequent sequences lie inside. I rather prefer to call the static Concat method directly and not the extension style:

var list = Enumerable.Concat(list1.Select(x => x),
                             list2.Where(x => true));

For more number of concats of sequences I carry the same static method as in OP:

public static IEnumerable<T> Concat<T>(params IEnumerable<T>[] sequences)
{
    return sequences.SelectMany(x => x);
}

So I can write:

return EnumerableEx.Concat
(
    list1.Select(x = > x),
    list2.Where(x => true),
    list3.OrderBy(x => x)
);

Looks better. The extra, otherwise redundant, class name I have to write is not a problem for me considering my sequences look cleaner with the Concat call. It's less of a problem in C# 6. You can just write:

return Concat(list1.Select(x = > x),
              list2.Where(x => true),
              list3.OrderBy(x => x));

Wished we had list concatenation operators in C#, something like:

list1 @ list2 // F#
list1 ++ list2 // Scala

Much cleaner that way.


For the case when you do have a collection of collections, i.e. a List<List<T>>, Enumerable.Aggregate is a more elegant way to combine all lists into one:

var combined = lists.Aggregate((acc, list) => { return acc.Concat(list); });

Use Enumerable.Concat like so:

var combined = foo.Concat(bar).Concat(baz)....;

You could always use Aggregate combined with Concat...

        var listOfLists = new List<List<int>>
        {
            new List<int> {1, 2, 3, 4},
            new List<int> {5, 6, 7, 8},
            new List<int> {9, 10}
        };

        IEnumerable<int> combined = new List<int>();
        combined = listOfLists.Aggregate(combined, (current, list) => current.Concat(list)).ToList();