How to concatenate two IEnumerable<T> into a new IEnumerable<T>?
Asked Answered
D

7

288

I have two instances of IEnumerable<T> (with the same T). I want a new instance of IEnumerable<T> which is the concatenation of both.

Is there a built-in method in .NET to do that or do I have to write it myself?

Delois answered 4/1, 2013 at 21:7 Comment(2)
You might want to bookmark code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b.Mechellemechlin
related, if it helps: Elegant way to combine multiple collections of elements?Albania
W
463

Yes, LINQ to Objects supports this with Enumerable.Concat:

var together = first.Concat(second);

NB: Should first or second be null you would receive a ArgumentNullException. To avoid this & treat nulls as you would an empty set, use the null coalescing operator like so:

var together = (first ?? Enumerable.Empty<string>()).Concat(second ?? Enumerable.Empty<string>()); //amending `<string>` to the appropriate type
Willywilly answered 4/1, 2013 at 21:7 Comment(5)
I always forget looking up extension methods, tx.Delois
@SamuelRossille Also don't forget that the names of actions you want to perform are likely close if not exactly called what you are after. Always browse IntelliSense, you learn a lot.Phonation
Is it bad to do second = first.Concat(second) ? will we have any concurrency issues?Nutter
@user2934433: Nope, that's absolutely fine.Willywilly
Just a quick note. It is required to import using System.Linq namespace at the top of code file to see the desired extension method in the IDE intellisense.Robespierre
S
26

The Concat method will return an object which implements IEnumerable<T> by returning an object (call it Cat) whose enumerator will attempt to use the two passed-in enumerable items (call them A and B) in sequence. If the passed-in enumerables represent sequences which will not change during the lifetime of Cat, and which can be read from without side-effects, then Cat may be used directly. Otherwise, it may be a good idea to call ToList() on Cat and use the resulting List<T> (which will represent a snapshot of the contents of A and B).

Some enumerables take a snapshot when enumeration begins, and will return data from that snapshot if the collection is modified during enumeration. If B is such an enumerable, then any change to B which occurs before Cat has reached the end of A will show up in Cat's enumeration, but changes which occur after that will not. Such semantics may likely be confusing; taking a snapshot of Cat can avoid such issues.

Stoat answered 31/1, 2014 at 17:29 Comment(0)
E
11

I know this is a relatively old post, but if you wanted to concatenate multiple IEnumerable's, I use the following

var joinedSel = new[] { first, second, third }.Where(x => x != null).SelectMany(x => x);

This eliminates any null IEnumerable's and allows for multiple concatenations.

Evulsion answered 21/7, 2021 at 9:3 Comment(0)
E
10

You can use below code for your solution:-

public void Linq94() 
{ 
    int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 }; 
    int[] numbersB = { 1, 3, 5, 7, 8 }; 

    var allNumbers = numbersA.Concat(numbersB); 

    Console.WriteLine("All numbers from both arrays:"); 
    foreach (var n in allNumbers) 
    { 
        Console.WriteLine(n); 
    } 
}
Ennoble answered 27/9, 2013 at 11:31 Comment(0)
G
1

Based off of craig1231's answer, I've created some extension methods...

    public static IEnumerable<T> JoinLists<T>(this IEnumerable<T> list1, IEnumerable<T> list2)
    {
        var joined = new[] { list1, list2 }.Where(x => x != null).SelectMany(x => x);
        return joined ?? Enumerable.Empty<T>();
    }
    public static IEnumerable<T> JoinLists<T>(this IEnumerable<T> list1, IEnumerable<T> list2, IEnumerable<T> list3)
    {
        var joined = new[] { list1, list2, list3 }.Where(x => x != null).SelectMany(x => x);
        return joined ?? Enumerable.Empty<T>();
    }
    public static IEnumerable<T> JoinMany<T>(params IEnumerable<T>[] array)
    {
        var final = array.Where(x => x != null).SelectMany(x => x);
        return final ?? Enumerable.Empty<T>();
    }
Gauguin answered 16/12, 2022 at 19:21 Comment(0)
C
0

In the meantime C#12 introduced the spread operator "..". You you can apply that on any IEnumerable easily

IEnumerable<int> enumerableA = [1,2];
IEnumerable<int> enumerableB = [3,4];
IEnumerable<int> merged = [ ..enumerableA, ..enumerableB ];

see: C#12 Collection Expressions

Comfort answered 1/3 at 6:25 Comment(0)
G
-3
// The answer that I was looking for when searching
public void Answer()
{
    IEnumerable<YourClass> first = this.GetFirstIEnumerableList();
    // Assign to empty list so we can use later
    IEnumerable<YourClass> second = new List<YourClass>();

    if (IwantToUseSecondList)
    {
        second = this.GetSecondIEnumerableList();  
    }
    IEnumerable<SchemapassgruppData> concatedList = first.Concat(second);
}
Guimar answered 31/1, 2014 at 10:58 Comment(1)
This appears to be just a repeat of the existing answers.Anecdotist

© 2022 - 2024 — McMap. All rights reserved.