356
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?


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).

Ryan M
  • 18,333
  • 31
  • 67
  • 74
hwiechers
  • 14,583
  • 8
  • 53
  • 62
  • 8
    What do you mean by "efficient"? The code is short enough as it is, so I assume you mean efficient in terms of CPU/RAM? – TToni Oct 10 '09 at 07:04
  • 4
    No, a quick look with Reflector shows that it uses a double-when-full buffer – erikkallen Oct 10 '09 at 10:24
  • Just be clear I need z to be a of type int[]. – hwiechers Oct 11 '09 at 10:56
  • 5
    I'm not really that concerned about efficiency. (I did say easier _or_ more efficient.) I asked the question to check how other people were handling this common task. – hwiechers Oct 11 '09 at 10:58

23 Answers23

416
var z = new int[x.Length + y.Length];
x.CopyTo(z, 0);
y.CopyTo(z, x.Length);
RaphaelH
  • 2,144
  • 2
  • 30
  • 43
Zed
  • 57,028
  • 9
  • 76
  • 100
  • 11
    @manthrax -> In its defense, C# tends to favor lists which are much more powerful than arrays. It seems the only functional purpose for using arrays is for Interop calls (Unmanaged C++). – Levi Fuller Oct 26 '15 at 22:40
  • 1
    @LeviFuller Another place where C# uses array is with variable-number `params` parameters. – ChrisW Jan 02 '16 at 13:33
  • @ChrisW I'd consider the params array more of a syntactical limitation. If you're going to concatenate it with another array, I'd still opt for .ToList() – Levi Fuller Jan 03 '16 at 17:01
  • 3
    @LeviFuller - it's odd that many system routines return arrays instead of lists. eg `System.IO.Directory.GetFiles()` returns an array of strings. – orion elenzil Jan 07 '16 at 17:55
  • 11
    This is not odd. An Array is immutable, a list isnt. Also a List uses more memory than an array, unless TrimExcess is called (which doesnt happen in ToList) – CSharpie Nov 09 '16 at 11:54
  • 5
    Also array is faster than list when accessing data, because list just wraps array inside and has overhead for calling indexer. – dmitry1100 May 26 '18 at 22:15
  • @LeviFuller Also when you send udp packet it must be byte[]. Converting from list will take overhead time – IC_ Aug 05 '18 at 05:47
  • 1
    What's the advantage of this answer? Is it faster? It seems like more writing. – Justin Helps Feb 24 '20 at 17:02
  • @JustinHelps: It is more efficient in terms of CPU/Memory. `.ToArray()` is not very efficient – Liero Aug 30 '21 at 07:59
112

Try this:

List<int> list = new List<int>();
list.AddRange(x);
list.AddRange(y);
int[] z = list.ToArray();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Adriaan Stander
  • 162,879
  • 31
  • 289
  • 284
  • 8
    Or even `List list = new List(x);` – Matthew Scharley Oct 10 '09 at 07:04
  • 11
    How is that more efficient than x.Concat(y)? It works and all, I'm just wondering if there is something that makes it better? – Mike Two Oct 10 '09 at 07:07
  • 14
    you might want to make the first line List list = new List(x.Length + y.Length); To avoid the resize that might happen as you call AddRange – Mike Two Oct 10 '09 at 07:09
  • 1
    @Mike: Noone said it was more efficient, though I suspect it is since the Array.Concat will involve *atleast* a memory allocation and two memory moves, which is no less than what the `List` solution requires. Besides that, it's about the only solution aside from Array.Concat. – Matthew Scharley Oct 10 '09 at 07:14
  • 8
    @Mathew Scharley. The question is asking for a more efficient solution. I know the title makes it sound like any old combination will do but the full question goes beyond that. Reading some of the answers I just feel some people are answering the title. So I thought that this answer should probably mention efficiency if it deserves the upvotes since that seemed to be the point of the question. – Mike Two Oct 10 '09 at 07:22
  • 1
    @Matthe - if you don't pre-size the `List`, there could be numerous copies and oversized capacity. – Marc Gravell Oct 10 '09 at 07:22
  • 1
    @Matthew Actually I'm not talking about Array.Concat. I don't think there is one. I was thinking of the extension method in the Enumerable class. It actually just constructs an iterator that iterates over both arrays. So there are no copies or resizes with that approach. – Mike Two Oct 10 '09 at 07:29
  • 2
    turns out that the AddRange is actually quite an expensive process, so the first answer on this board should be the prefered approach: http://www.dotnetperls.com/insertrange – Liam Jul 25 '12 at 16:38
  • 1
    @Liam in this day and age, we do not really care about copying arrays, especially small scale. we can perform thousands of operations a second, who cares about a few actions extra. – jordan Oct 09 '13 at 22:35
  • 1
    @jordan.peoples it's possible that it will matter to someone reading this, it depends on your job. Think about your closest nuclear power plant, or pipeline. You would want Liam writing the code that runs them. – amalgamate Sep 16 '14 at 18:49
  • @amalgamate it still would not matter, i guarantee you that there are buffers for processing time and lag already built into those systems. They are probably using computers that cost hundreds of thousands of dollars, and they are not worries about byte copying and hundreths of milliseconds of processing time. – jordan Sep 16 '14 at 18:54
  • 1
    @jordan.peoples as someone who works in one of those industries, I can promise that is not always true (that is about having the best equipment). Some (certainly not all) of the critical infrastructure on this planet is running on systems that are allot older then the new hires that work on them. Granted many of these will not run .net anyway. I promise you, however, that there are some industries active today where processing time is still critical. – amalgamate Sep 16 '14 at 19:23
  • @amalgamate I agree with you, which i should have said in my last post, but your examples- oil pipelines (my line of work) and nuclear power plants, (hopefully) have no need to worry about processing time. I think better examples would be aircraft autopilot programs, or health care systems etc... – jordan Sep 16 '14 at 19:27
62

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}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    Isn't there already an extension method that works on any IEnumerable? – Mike Two Oct 10 '09 at 07:17
  • 2
    Yes, and I'd use that happily for most cases. But they have lots of overheads. It depends; 98% of the time the overheads are fine. If you are in the 2%, though, then some direct memcopy/array work is handy. – Marc Gravell Oct 10 '09 at 07:21
  • 1
    @nawfal, how is `Copy` faster than `CopyTo`? Care to elaborate? – skrebbel Nov 23 '12 at 12:35
  • 1
    @skrebbel mine was an inaccurate comment. I did some testing back then and I found Copy faster. But now it seems they are just equal. What I might have found back then could be that overall the Marc's approach is more efficient since he is passing the same instance back while in Zed's approach he is creating a new array. Apologies :) – nawfal Nov 23 '12 at 13:07
  • 1
    @Shimmy It would not. Inside this method x is but a local variable, passing x as a ref to the resize method would create a new array and alter (the local variable) x to point to it. Or to rephrase: x passed into the resize and x inside the extension method is the same variable, but x is not passed into the extension method as a ref, so x is a different variable than the variable in the scope this extension was called from. – AnorZaken Feb 05 '15 at 20:34
48

This is it:

using System.Linq;

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

// Concatenate array1 and array2.
int[] result1 = array1.Concat(array2).ToArray();
gunr2171
  • 16,104
  • 25
  • 61
  • 88
Roland
  • 535
  • 4
  • 2
  • 13
    You mean `int[] result = array1.ToList().Concat(array2.ToList()).toArray();` You cannot apply Concat on arrays directly I believe – Michail Michailidis Oct 21 '14 at 19:57
  • 1
    The code correct, as arrays in C# implements the IEnumerable interface. (See 6th paragraph of Remarks section in the following documentation: http://msdn.microsoft.com/en-us/library/system.array.aspx) – Tormod Haugene Nov 04 '14 at 09:46
  • 5
    This solution -- z = x.Concat(y) -- is mentioned in the original question above. – Jon Schneider Feb 20 '15 at 19:32
  • 3
    This is what happens without the `toArray()` `Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'string[]'. An explicit conversion exists (are you missing a cast?) ` – Tibor Udvari Jun 16 '15 at 11:32
  • 1
  • 5
    This is not a direct answer. OP asked for `int[] result = ?`, you are hiding the problem of your answer behind your `var` in that your result will be `IEnumerable`, not `int[]`. (one of the reasons why I don't like `var` on method returns) – David S. Nov 30 '16 at 14:33
  • 2
    This method is what is used in the question so this answer provides no new info, and without the `.ToArray()` call, this code will not return an actual array so it's also an incorrect answer. – Mani Gandham Dec 10 '16 at 14:52
44

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}
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
deepee1
  • 12,878
  • 4
  • 30
  • 43
  • Nice function, thanks! Changed `params T[][]` to `this T[][]` to make it an extension. – Mark Oct 10 '12 at 19:14
14

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.

amalgamate
  • 2,200
  • 5
  • 22
  • 44
  • In fairness to the methods that used methods, the Methods probably added roughly 10,000 ticks on my system. – amalgamate Nov 14 '14 at 20:57
  • 3
    I ran your code in visual studio 2013 in release mode and found that, if the tested array is not so tiny as yours (like 1000 elements), `CopyTo` will be the fasest and ~3x faster than `Roll your own`. – Mr. Ree Jul 07 '15 at 01:48
  • @Mr.Ree Yes, my array was truly tiny wasn't it. Thanks. Would be interested to see if Block copy does even better... – amalgamate Jul 07 '15 at 15:13
  • 1
    Thank you for your complete research. But there is a small mistake in the method `targetList.Concat(y)`. This instruction does not do any real work, it only creates an enumerator. The correct solution should be something like `var z = targetList.Concat(y).ToArray();`. My tests of your code in .NET 6 also showed that `CopyTo` is the best way. – Oleg Nesterov Feb 05 '23 at 17:41
12

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.

Community
  • 1
  • 1
Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • I tried converting this to vb code but it didn't work. Apparently vb.net doesn't have the sizeOf function – Tyler Wayne Jan 01 '22 at 06:59
  • 1
    @TylerWayne that is true, sucks right. You could replace `sizeOf(int)` with the literal `4`. Perhaps declaring a constant. – Jodrell Jan 06 '22 at 15:30
9

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.

Mike Two
  • 44,935
  • 9
  • 80
  • 96
8

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

    }
Saleh Saeednia
  • 121
  • 1
  • 3
8

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.

Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
Darkseal
  • 9,205
  • 8
  • 78
  • 111
6
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;
}
Sergey Shteyn
  • 61
  • 1
  • 1
  • 2
    At StackOverflow please don't just paste code, but also explain your approach. In this specific case you may also have to explain what your late answer adds to the answers already given (and accepted) – Gert Arnold Aug 06 '12 at 21:53
  • 1
    Not sure what that "this" is doing before the first param, but for the rest, this is an excellent function. Generic, and with an infinite amount of parameters. – Nyerguds Sep 24 '12 at 10:40
  • 2
    Hi Nyerguds. To answer your question, the "this" keyword is used to make the function an extension method. For more information on extension methods check out this [MSDN article](http://msdn.microsoft.com/en-us/library/vstudio/bb383977.aspx) – JFish222 Jan 31 '13 at 02:29
3

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.

TToni
  • 9,145
  • 1
  • 28
  • 42
3

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.

nurchi
  • 770
  • 11
  • 24
  • Thre foreach / yield return is redundant. You could return directly the `merged` variable. So basicaly your merge is the same as Concat, isn't it? `var z = x1.Concat(x2).Contact(x3);` `za=z.ToArray();` – Liero Aug 30 '21 at 07:51
  • @Liero, you're not wrong, but the foreach/yield return is required in this case (you probably know this, but the comment is for a future reader). When merging large sets of data, you don't always want the whole thing at once (i.e. the `.ToArray()` method, which could take a large amount of time). I have `var za=x.ToArray()` as an example, in general, the merged result (of type `IEnumerable`) needs to be iterated in a loop to go through each result, one per iteration. – nurchi Sep 28 '21 at 22:25
  • Sure, you don't need ToArray, but you can (should) still return the 'merged` variable in the first example, which is IEnumerable – Liero Sep 29 '21 at 00:48
  • That is what `yield return` does (unless I misunderstood your comment). – nurchi Oct 13 '21 at 15:56
2

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];
Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
dreadwail
  • 15,098
  • 21
  • 65
  • 96
2

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.

Community
  • 1
  • 1
Marko Gresak
  • 7,950
  • 5
  • 40
  • 46
1

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" ;)

Siewers
  • 22,626
  • 3
  • 20
  • 31
1

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();
psxls
  • 6,807
  • 6
  • 30
  • 50
0

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

Community
  • 1
  • 1
mezoid
  • 28,090
  • 37
  • 107
  • 148
  • 2
    Concat would also work for List. That's what is great about Concat, it works on any IEnumerable<> – Mike Two Oct 10 '09 at 07:12
0
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.

drowa
  • 682
  • 5
  • 13
  • I'd recommend trying to find newer questions or ones hat don't already have numerous answers - including one pretty much just like yours. – Andrew Barber May 10 '14 at 01:19
  • I proposed this solution because I think it summarizes what is good from the other ones. It was crafted. – drowa May 10 '14 at 05:50
0

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();
Michail Michailidis
  • 11,792
  • 6
  • 63
  • 106
-3
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]);
}
Kevin
  • 16,549
  • 8
  • 60
  • 74
presty prajna
  • 390
  • 1
  • 3
  • 7
-3

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.

Neil Meyer
  • 473
  • 4
  • 15
-5

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

  • 4
    `Union` is not a very good way to do this as it implicitly calls `Distinct` and removes any duplicates from the joined collection. `Concat` is much better, but it's already in the original question. – nurchi Jan 17 '17 at 00:07