How do I concatenate two arrays in C#?

C#Arrays.NetLinq

C# Problem Overview


int[] x = new int [] { 1, 2, 3};
int[] y = new int [] { 4, 5 };

int[] z = // your answer here...

Debug.Assert(z.SequenceEqual(new int[] { 1, 2, 3, 4, 5 }));

Right now I use

int[] z = x.Concat(y).ToArray();

Is there an easier or more efficient method?

C# Solutions


Solution 1 - C#

var z = new int[x.Length + y.Length];
x.CopyTo(z, 0);
y.CopyTo(z, x.Length);

Solution 2 - C#

Try this:

List<int> list = new List<int>();
list.AddRange(x);
list.AddRange(y);
int[] z = list.ToArray();

Solution 3 - C#

You could write an extension method:

public static T[] Concat<T>(this T[] x, T[] y)
{
    if (x == null) throw new ArgumentNullException("x");
    if (y == null) throw new ArgumentNullException("y");
    int oldLen = x.Length;
    Array.Resize<T>(ref x, x.Length + y.Length);
    Array.Copy(y, 0, x, oldLen, y.Length);
    return x;
}

Then:

int[] x = {1,2,3}, y = {4,5};
int[] z = x.Concat(y); // {1,2,3,4,5}

Solution 4 - C#

This is it:

using System.Linq;

int[] array1 = { 1, 3, 5 };
int[] array2 = { 0, 2, 4 };

// Concatenate array1 and array2.
var result1 = array1.Concat(array2);

Solution 5 - C#

I settled on a more general-purpose solution that allows concatenating an arbitrary set of one-dimensional arrays of the same type. (I was concatenating 3+ at a time.)

My function:

    public static T[] ConcatArrays<T>(params T[][] list)
    {
        var result = new T[list.Sum(a => a.Length)];
        int offset = 0;
        for (int x = 0; x < list.Length; x++)
        {
            list[x].CopyTo(result, offset);
            offset += list[x].Length;
        }
        return result;
    }

And usage:

        int[] a = new int[] { 1, 2, 3 };
        int[] b = new int[] { 4, 5, 6 };
        int[] c = new int[] { 7, 8 };
        var y = ConcatArrays(a, b, c); //Results in int[] {1,2,3,4,5,6,7,8}

Solution 6 - C#

I know the OP was only mildly curious about performance. That larger arrays may get a different result (see @kurdishTree). And that it usually does not matter (@jordan.peoples). None the less, I was curious and therefore lost my mind ( as @TigerShark was explaining).... I mean that I wrote a simple test based on the original question.... and all the answers....

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace concat
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] x = new int [] { 1, 2, 3};
            int[] y = new int [] { 4, 5 };
            
            
            int itter = 50000;
            Console.WriteLine("test iterations: {0}", itter);

            DateTime startTest = DateTime.Now;
            for(int  i = 0; i < itter; i++)
            {
                int[] z;
                z = x.Concat(y).ToArray();
            }
            Console.WriteLine ("Concat Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks );

            startTest = DateTime.Now;
            for(int  i = 0; i < itter; i++)
            {
                var vz = new int[x.Length + y.Length];
                x.CopyTo(vz, 0);
                y.CopyTo(vz, x.Length);
            }
            Console.WriteLine ("CopyTo Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks );

            startTest = DateTime.Now;
            for(int  i = 0; i < itter; i++)
            {
                List<int> list = new List<int>();
                list.AddRange(x);
                list.AddRange(y);
                int[] z = list.ToArray();
            }
            Console.WriteLine("list.AddRange Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                int[] z = Methods.Concat(x, y);
            }
            Console.WriteLine("Concat(x, y) Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                int[] z = Methods.ConcatArrays(x, y);
            }
            Console.WriteLine("ConcatArrays Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                int[] z = Methods.SSConcat(x, y);
            }
            Console.WriteLine("SSConcat Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int k = 0; k < itter; k++)
            {
                int[] three = new int[x.Length + y.Length];

                int idx = 0;

                for (int i = 0; i < x.Length; i++)
                    three[idx++] = x[i];
                for (int j = 0; j < y.Length; j++)
                    three[idx++] = y[j];
            }
            Console.WriteLine("Roll your own Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);


            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                int[] z = Methods.ConcatArraysLinq(x, y);
            }
            Console.WriteLine("ConcatArraysLinq Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                int[] z = Methods.ConcatArraysLambda(x, y);
            }
            Console.WriteLine("ConcatArraysLambda Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                List<int> targetList = new List<int>(x);
                targetList.Concat(y);
            }
            Console.WriteLine("targetList.Concat(y) Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                int[] result = x.ToList().Concat(y.ToList()).ToArray();
            }
            Console.WriteLine("x.ToList().Concat(y.ToList()).ToArray() Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
        }
    }
    static class Methods
    {
        public static T[] Concat<T>(this T[] x, T[] y)
        {
            if (x == null) throw new ArgumentNullException("x");
            if (y == null) throw new ArgumentNullException("y");
            int oldLen = x.Length;
            Array.Resize<T>(ref x, x.Length + y.Length);
            Array.Copy(y, 0, x, oldLen, y.Length);
            return x;
        }

        public static T[] ConcatArrays<T>(params T[][] list)
        {
            var result = new T[list.Sum(a => a.Length)];
            int offset = 0;
            for (int x = 0; x < list.Length; x++)
            {
                list[x].CopyTo(result, offset);
                offset += list[x].Length;
            }
            return result;
        }


        public static T[] SSConcat<T>(this T[] first, params T[][] arrays)
        {
            int length = first.Length;
            foreach (T[] array in arrays)
            {
                length += array.Length;
            }
            T[] result = new T[length];
            length = first.Length;
            Array.Copy(first, 0, result, 0, first.Length);
            foreach (T[] array in arrays)
            {
                Array.Copy(array, 0, result, length, array.Length);
                length += array.Length;
            }
            return result;
        }

        public static T[] ConcatArraysLinq<T>(params T[][] arrays)
        {
            return (from array in arrays
                    from arr in array
                    select arr).ToArray();
        }

        public static T[] ConcatArraysLambda<T>(params T[][] arrays)
        {
            return arrays.SelectMany(array => array.Select(arr => arr)).ToArray();
        }
    }

}

The result was:

enter image description here

Roll your own wins.

Solution 7 - C#

More efficient (faster) to use Buffer.BlockCopy over Array.CopyTo,

int[] x = new int [] { 1, 2, 3};
int[] y = new int [] { 4, 5 };

int[] z = new int[x.Length + y.Length];
var byteIndex = x.Length * sizeof(int);
Buffer.BlockCopy(x, 0, z, 0, byteIndex);
Buffer.BlockCopy(y, 0, z, byteIndex, y.Length * sizeof(int));

I wrote a simple test program that "warms up the Jitter", compiled in release mode and ran it without a debugger attached, on my machine.

For 10,000,000 iterations of the example in the question

>Concat took 3088ms > >CopyTo took 1079ms > >BlockCopy took 603ms

If I alter the test arrays to two sequences from 0 to 99 then I get results similar to this,

>Concat took 45945ms > >CopyTo took 2230ms > >BlockCopy took 1689ms

From these results I can assert that the CopyTo and BlockCopy methods are significantly more efficient than Concat and furthermore, if performance is a goal, BlockCopy has value over CopyTo.

To caveat this answer, if performance doesn't matter, or there will be few iterations choose the method you find easiest. Buffer.BlockCopy does offer some utility for type conversion beyond the scope of this question.

Solution 8 - C#

Be careful with the Concat method. The post Array Concatenation in C# explains that:

var z = x.Concat(y).ToArray();

Will be inefficient for large arrays. That means the Concat method is only for meduim-sized arrays (up to 10000 elements).

Solution 9 - C#

You can take the ToArray() call off the end. Is there a reason you need it to be an array after the call to Concat?

Calling Concat creates an iterator over both arrays. It does not create a new array so you have not used more memory for a new array. When you call ToArray you actually do create a new array and take up the memory for the new array.

So if you just need to easily iterate over both then just call Concat.

Solution 10 - C#

Here's my answer:

int[] z = new List<string>()
    .Concat(a)
    .Concat(b)
    .Concat(c)
    .ToArray();

This method can be used at initialization level, for example to define a static concatenation of static arrays:

public static int[] a = new int [] { 1, 2, 3, 4, 5 };
public static int[] b = new int [] { 6, 7, 8 };
public static int[] c = new int [] { 9, 10 };

public static int[] z = new List<string>()
    .Concat(a)
    .Concat(b)
    .Concat(c)
    .ToArray();

However, it comes with two caveats that you need to consider:

  • The Concat method creates an iterator over both arrays: it does not create a new array, thus being efficient in terms of memory used: however, the subsequent ToArray  will negate such advantage, since it will actually create a new array and take up the memory for the new array.
  • As @Jodrell said, Concat would be rather inefficient for large arrays: it should only be used for medium-sized arrays.

If aiming for performance is a must, the following method can be used instead:

/// <summary>
/// Concatenates two or more arrays into a single one.
/// </summary>
public static T[] Concat<T>(params T[][] arrays)
{
    // return (from array in arrays from arr in array select arr).ToArray();

    var result = new T[arrays.Sum(a => a.Length)];
    int offset = 0;
    for (int x = 0; x < arrays.Length; x++)
    {
        arrays[x].CopyTo(result, offset);
        offset += arrays[x].Length;
    }
    return result;
}

Or (for one-liners fans):

int[] z = (from arrays in new[] { a, b, c } from arr in arrays select arr).ToArray();

Although the latter method is much more elegant, the former one is definitely better for performance.

For additional info, please refer to this post on my blog.

Solution 11 - C#

Late Answer :-).

public static class ArrayExtention
    {

        public static T[] Concatenate<T>(this T[] array1, T[] array2)
        {
            T[] result = new T[array1.Length + array2.Length];
            array1.CopyTo(result, 0);
            array2.CopyTo(result, array1.Length);
            return result;
        }

    }

Solution 12 - C#

public static T[] Concat<T>(this T[] first, params T[][] arrays)
{
    int length = first.Length;
    foreach (T[] array in arrays)
    {
        length += array.Length;
    }
    T[] result = new T[length];
    length = first.Length;
    Array.Copy(first, 0, result, 0, first.Length);
    foreach (T[] array in arrays)
    {
        Array.Copy(array, 0, result, length, array.Length);
        length += array.Length;
    }
    return result;
}

Solution 13 - C#

The most efficient structure in terms of RAM (and CPU) to hold the combined array would be a special class that implements IEnumerable (or if you wish even derives from Array) and links internally to the original arrays to read the values. AFAIK Concat does just that.

In your sample code you could omit the .ToArray() though, which would make it more efficient.

Solution 14 - C#

Sorry to revive an old thread, but how about this:

static IEnumerable<T> Merge<T>(params T[][] arrays)
{
	var merged = arrays.SelectMany(arr => arr);
	
	foreach (var t in merged)
		yield return t;
}

Then in your code:

int[] x={1, 2, 3};
int[] y={4, 5, 6};

var z=Merge(x, y);	// 'z' is IEnumerable<T>

var za=z.ToArray();	// 'za' is int[]

Until you call .ToArray(), .ToList(), or .ToDictionary(...), the memory is not allocated, you are free to "build your query" and either call one of those three to execute it or simply go through them all by using foreach (var i in z){...} clause which returns an item at a time from the yield return t; above...

The above function can be made into an extension as follows:

static IEnumerable<T> Merge<T>(this T[] array1, T[] array2)
{
	var merged = array1.Concat(array2);
	
	foreach (var t in merged)
		yield return t;
}

So in the code, you can do something like:

int[] x1={1, 2, 3};
int[] x2={4, 5, 6};
int[] x3={7, 8};

var z=x1.Merge(x2).Merge(x3);	// 'z' is IEnumerable<T>

var za=z.ToArray();	// 'za' is int[]

The rest is the same as before.

One other improvement to this would be changing T[] into IEnumerable<T> (so the params T[][] would become params IEnumerable<T>[]) to make these functions accept more than just arrays.

Hope this helps.

Solution 15 - C#

You can do it the way you have referred to, or if you want to get really manual about it, you can roll your own loop:

string[] one = new string[] { "a", "b" };
string[] two = new string[] { "c", "d" };
string[] three;

three = new string[one.Length + two.Length];

int idx = 0;

for (int i = 0; i < one.Length; i++)
    three[idx++] = one[i];
for (int j = 0; j < two.Length; j++)
    three[idx++] = two[j];

Solution 16 - C#

I've found an elegant one line solution using LINQ or Lambda expression, both work the same (LINQ is converted to Lambda when program is compiled). The solution works for any array type and for any number of arrays.

Using LINQ:

public static T[] ConcatArraysLinq<T>(params T[][] arrays)
{
    return (from array in arrays
            from arr in array
            select arr).ToArray();
}

Using Lambda:

public static T[] ConcatArraysLambda<T>(params T[][] arrays)
{
    return arrays.SelectMany(array => array.Select(arr => arr)).ToArray();
}

I've provided both for one's preference. Performance wise @Sergey Shteyn's or @deepee1's solutions are a bit faster, Lambda expression being the slowest. Time taken is dependant on type(s) of array elements, but unless there are millions of calls, there is no significant difference between the methods.

Solution 17 - C#

What you need to remember is that when using LINQ you are utilizing delayed execution. The other methods described here all work perfectly, but they are executed immediately. Furthermore the Concat() function is probably optimized in ways you can't do yourself (calls to internal API's, OS calls etc.). Anyway, unless you really need to try and optimize, you're currently on your path to "the root of all evil" ;)

Solution 18 - C#

Try the following:

T[] r1 = new T[size1];
T[] r2 = new T[size2];

List<T> targetList = new List<T>(r1);
targetList.Concat(r2);
T[] targetArray = targetList.ToArray();

Solution 19 - C#

For int[] what you've done looks good to me. astander's answer would also work well for List<int>.

Solution 20 - C#

static class Extensions
{
    public static T[] Concat<T>(this T[] array1, params T[] array2) => ConcatArray(array1, array2);

    public static T[] ConcatArray<T>(params T[][] arrays)
    {
        int l, i;

        for (l = i = 0; i < arrays.Length; l += arrays[i].Length, i++);

        var a = new T[l];

        for (l = i = 0; i < arrays.Length; l += arrays[i].Length, i++)
            arrays[i].CopyTo(a, l);

        return a;
    }
}

I think the above solution is more general & lighter than the others I saw here. It is more general because it doesn't limit concatenation for only two arrays and is lighter because it doesn't use LINQ nor List.

Note the solution is concise and the added generality doesn't add significant runtime overhead.

Solution 21 - C#

For smaller arrays <10000 elements:

using System.Linq;

int firstArray = {5,4,2};
int secondArray = {3,2,1};

int[] result = firstArray.ToList().Concat(secondArray.ToList()).toArray();

Solution 22 - C#

I think a list would be apt for this purpose.

You can create a list like this.

List<int> Items = new List<int>();  

Then you can pretty easily just use a for each loop to iterate over any number of arrays and add them to the list.

foreach (int i in nameOfArray)
{
    Items.Add(i); 
}

If you use a list it would remove the problem of an out of bounds exception. A list can be used for all the same functionality as an array. The only meaningful difference is the lack of a hard limit in the number of items.

Solution 23 - C#

int[] scores = { 100, 90, 90, 80, 75, 60 };
int[] alice = { 50, 65, 77, 90, 102 };
int[] scoreBoard = new int[scores.Length + alice.Length];

int j = 0;
for (int i=0;i<(scores.Length+alice.Length);i++)  // to combine two arrays
{
    if(i<scores.Length)
    {
        scoreBoard[i] = scores[i];
    }
    else
    {
        scoreBoard[i] = alice[j];
        j = j + 1;
        
    }
}


for (int l = 0; l < (scores.Length + alice.Length); l++)
{
    Console.WriteLine(scoreBoard[l]);
}

Solution 24 - C#

var z = x.Concat(y).ToArray();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionhwiechersView Question on Stackoverflow
Solution 1 - C#ZedView Answer on Stackoverflow
Solution 2 - C#Adriaan StanderView Answer on Stackoverflow
Solution 3 - C#Marc GravellView Answer on Stackoverflow
Solution 4 - C#RolandView Answer on Stackoverflow
Solution 5 - C#deepee1View Answer on Stackoverflow
Solution 6 - C#amalgamateView Answer on Stackoverflow
Solution 7 - C#JodrellView Answer on Stackoverflow
Solution 8 - C#kurdishTreeView Answer on Stackoverflow
Solution 9 - C#Mike TwoView Answer on Stackoverflow
Solution 10 - C#DarksealView Answer on Stackoverflow
Solution 11 - C#Saleh SaeedniaView Answer on Stackoverflow
Solution 12 - C#Sergey ShteynView Answer on Stackoverflow
Solution 13 - C#TToniView Answer on Stackoverflow
Solution 14 - C#nurchiView Answer on Stackoverflow
Solution 15 - C#dreadwailView Answer on Stackoverflow
Solution 16 - C#Marko GresakView Answer on Stackoverflow
Solution 17 - C#SiewersView Answer on Stackoverflow
Solution 18 - C#کی‌راد عباسیView Answer on Stackoverflow
Solution 19 - C#mezoidView Answer on Stackoverflow
Solution 20 - C#drowaView Answer on Stackoverflow
Solution 21 - C#Michail MichailidisView Answer on Stackoverflow
Solution 22 - C#Neil MeyerView Answer on Stackoverflow
Solution 23 - C#presty prajnaView Answer on Stackoverflow
Solution 24 - C#Milad DorakiView Answer on Stackoverflow