279

Is there a built in function in .NET 2.0 that will take two arrays and merge them into one array?

The arrays are both of the same type. I'm getting these arrays from a widely used function within my code base and can't modify the function to return the data in a different format.

I'm looking to avoid writing my own function to accomplish this if possible.

leppie
  • 112,162
  • 17
  • 191
  • 293
kbrinley
  • 3,134
  • 3
  • 18
  • 9

24 Answers24

520

In C# 3.0 you can use LINQ's Concat method to accomplish this easily:

int[] front = { 1, 2, 3, 4 };
int[] back = { 5, 6, 7, 8 };
int[] combined = front.Concat(back).ToArray();

In C# 2.0 you don't have such a direct way, but Array.Copy is probably the best solution:

int[] front = { 1, 2, 3, 4 };
int[] back = { 5, 6, 7, 8 };

int[] combined = new int[front.Length + back.Length];
Array.Copy(front, combined, front.Length);
Array.Copy(back, 0, combined, front.Length, back.Length);

This could easily be used to implement your own version of Concat.

Jon Schneider
  • 23,615
  • 19
  • 137
  • 163
OwenP
  • 24,208
  • 13
  • 63
  • 97
  • 2
    I like that LINQ implementation. I really need to make the jump and get into LINQ soon... – GEOCHET Sep 12 '08 at 15:20
  • 1
    Rich, the best part about the LINQ implementation is not only is it concise, it's also just as efficient as the 2.0 version, since it works against IEnumerable. – Brad Wilson Sep 12 '08 at 23:13
  • This answer includes this way and also gives some benchmarking results: http://stackoverflow.com/questions/415291/best-way-to-combine-two-or-more-byte-arrays-in-c-sharp – Demir Aug 09 '12 at 09:10
  • 1
    This is probably the easiest way but this is not going to be efficient for large arrays, since Concat is implemented using foreach loops + yield (see reference source). A solution with BlockCopy will be faster. – tigrou Jun 28 '17 at 15:59
  • .Contat() is definitely the simplest. Just a tip from my experience, if you want to remove duplicates just call .Distinct() afterwards. – Brian Tacker Jul 05 '17 at 21:28
  • 1
    Just a small heads up: if you only want to iterate through the combined result, no need to convert it to an array. That final operation does an array copy. It won't have to do that if you iterate through an IEnumerable. Of course, there could be good reasons to have it be an array. – Jonas Dec 05 '18 at 09:57
134

If you can manipulate one of the arrays, you can resize it before performing the copy:

T[] array1 = getOneArray();
T[] array2 = getAnotherArray();
int array1OriginalLength = array1.Length;
Array.Resize<T>(ref array1, array1OriginalLength + array2.Length);
Array.Copy(array2, 0, array1, array1OriginalLength, array2.Length);

Otherwise, you can make a new array

T[] array1 = getOneArray();
T[] array2 = getAnotherArray();
T[] newArray = new T[array1.Length + array2.Length];
Array.Copy(array1, newArray, array1.Length);
Array.Copy(array2, 0, newArray, array1.Length, array2.Length);

More on available Array methods on MSDN.

Community
  • 1
  • 1
Blair Conrad
  • 219,342
  • 25
  • 129
  • 110
123

Use LINQ:

var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = arr1.Union(arr2).ToArray();

Keep in mind, this will remove duplicates. If you want to keep duplicates, use Concat.

Jack Marchetti
  • 15,254
  • 13
  • 78
  • 116
Simon B.
  • 1,319
  • 1
  • 8
  • 2
51

If you don't want to remove duplicates, then try this

Use LINQ:

var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = arr1.Concat(arr2).ToArray();
Smith
  • 5,562
  • 16
  • 94
  • 159
13

First, make sure you ask yourself the question "Should I really be using an Array here"?

Unless you're building something where speed is of the utmost importance, a typed List, like List<int> is probably the way to go. The only time I ever use arrays are for byte arrays when sending stuff over the network. Other than that, I never touch them.

CodesInChaos
  • 103,479
  • 23
  • 206
  • 257
  • Big +1 here. Note that best practice is to avoid exposing `List` in public APIs: http://blogs.msdn.com/b/kcwalina/archive/2005/09/26/474010.aspx – TrueWill Jan 07 '12 at 16:18
11

Easier would just be using LINQ:

var array = new string[] { "test" }.ToList();
var array1 = new string[] { "test" }.ToList();
array.AddRange(array1);
var result = array.ToArray();

First convert the arrays to lists and merge them... After that just convert the list back to an array :)

Peter Mortensen
  • 30,030
  • 21
  • 100
  • 124
Angelo Ortega
  • 431
  • 4
  • 9
7

I think you can use Array.Copy for this. It takes a source index and destination index so you should be able to append the one array to the other. If you need to go more complex than just appending one to the other, this may not be the right tool for you.

GEOCHET
  • 20,745
  • 15
  • 72
  • 98
6

Everyone has already had their say but I think this more readable than the "use as Extension method" approach:

var arr1 = new[] { 1, 2, 3, 4, 5 };
var arr2 = new[] { 6, 7, 8, 9, 0 };
var arr = Queryable.Concat(arr1, arr2).ToArray();

However it can only be used when bringing together 2 arrays.

John Reilly
  • 5,159
  • 4
  • 34
  • 55
6

This is what I came up with. Works for a variable number of arrays.

public static T[] ConcatArrays<T>(params T[][] args)
    {
        if (args == null)
            throw new ArgumentNullException();

        var offset = 0;
        var newLength = args.Sum(arr => arr.Length); 
        var newArray = new T[newLength];

        foreach (var arr in args)
        {
            Buffer.BlockCopy(arr, 0, newArray, offset, arr.Length);
            offset += arr.Length;
        }

        return newArray;
    }

...

var header = new byte[] { 0, 1, 2};
var data = new byte[] { 3, 4, 5, 6 };
var checksum = new byte[] {7, 0};
var newArray = ConcatArrays(header, data, checksum);
//output byte[9] { 0, 1, 2, 3, 4, 5, 6, 7, 0 }
cj.burrow
  • 71
  • 1
  • 6
5

Assuming the destination array has enough space, Array.Copy() will work. You might also try using a List<T> and its .AddRange() method.

Joel Coehoorn
  • 380,066
  • 110
  • 546
  • 781
4

Personally, I prefer my own Language Extensions, which I add or remove at will for rapid prototyping.

Following is an example for strings.

//resides in IEnumerableStringExtensions.cs
public static class IEnumerableStringExtensions
{
   public static IEnumerable<string> Append(this string[] arrayInitial, string[] arrayToAppend)
   {
       string[] ret = new string[arrayInitial.Length + arrayToAppend.Length];
       arrayInitial.CopyTo(ret, 0);
       arrayToAppend.CopyTo(ret, arrayInitial.Length);

       return ret;
   }
}

It is much faster than LINQ and Concat. Faster still, is using a custom IEnumerable Type-wrapper which stores references/pointers of passed arrays and allows looping over the entire collection as if it were a normal array. (Useful in HPC, Graphics Processing, Graphics render...)

Your Code:

var someStringArray = new[]{"a", "b", "c"};
var someStringArray2 = new[]{"d", "e", "f"};
someStringArray.Append(someStringArray2 ); //contains a,b,c,d,e,f

For the entire code and a generics version see: https://gist.github.com/lsauer/7919764

Note: This returns an unextended IEnumerable object. To return an extended object is a bit slower.

I compiled such extensions since 2002, with a lot of credits going to helpful people on CodeProject and 'Stackoverflow'. I will release these shortly and put the link up here.

Lorenz Lo Sauer
  • 22,244
  • 13
  • 79
  • 86
3

Just to have it noted as an option: if the arrays you are working with are of a primitive type – Boolean (bool), Char, SByte, Byte, Int16 (short), UInt16, Int32 (int), UInt32, Int64 (long), UInt64, IntPtr, UIntPtr, Single, or Double – then you could (or should?) try using Buffer.BlockCopy. According to the MSDN page for the Buffer class:

This class provides better performance for manipulating primitive types than similar methods in the System.Array class.

Using the C# 2.0 example from @OwenP's answer as a starting point, it would work as follows:

int[] front = { 1, 2, 3, 4 };
int[] back = { 5, 6, 7, 8 };

int[] combined = new int[front.Length + back.Length];
Buffer.BlockCopy(front, 0, combined, 0, front.Length);
Buffer.BlockCopy(back, 0, combined, front.Length, back.Length);

There is barely any difference in syntax between Buffer.BlockCopy and the Array.Copy that @OwenP used, but this should be faster (even if only slightly).

Community
  • 1
  • 1
Solomon Rutzky
  • 44,393
  • 7
  • 124
  • 161
3

I needed a solution to combine an unknown number of arrays.

Surprised nobody else provided a solution using SelectMany with params.

 private static T[] Combine<T>(params IEnumerable<T>[] items) =>
                    items.SelectMany(i => i).Distinct().ToArray();

If you don't want distinct items just remove distinct.

 public string[] Reds = new [] { "Red", "Crimson", "TrafficLightRed" };
 public string[] Greens = new [] { "Green", "LimeGreen" };
 public string[] Blues = new [] { "Blue", "SkyBlue", "Navy" };

 public string[] Colors = Combine(Reds, Greens, Blues);

Note: There is definitely no guarantee of ordering when using distinct.

Simon_Weaver
  • 130,769
  • 75
  • 612
  • 659
2

In case someone else is looking for how to merge two image byte arrays:

        private void LoadImage()
        {
            string src = string.empty;
            byte[] mergedImageData = new byte[0];

            mergedImageData = MergeTwoImageByteArrays(watermarkByteArray, backgroundImageByteArray);
            src = "data:image/png;base64," + Convert.ToBase64String(mergedImageData);
            MyImage.ImageUrl = src;
        }

        private byte[] MergeTwoImageByteArrays(byte[] imageBytes, byte[] imageBaseBytes)
        {
            byte[] mergedImageData = new byte[0];
            using (var msBase = new MemoryStream(imageBaseBytes))
            {
                System.Drawing.Image imgBase = System.Drawing.Image.FromStream(msBase);
                Graphics gBase = Graphics.FromImage(imgBase);
                using (var msInfo = new MemoryStream(imageBytes))
                {
                    System.Drawing.Image imgInfo = System.Drawing.Image.FromStream(msInfo);
                    Graphics gInfo = Graphics.FromImage(imgInfo);
                    gBase.DrawImage(imgInfo, new Point(0, 0));
                    //imgBase.Save(Server.MapPath("_____testImg.png"), ImageFormat.Png);
                    MemoryStream mergedImageStream = new MemoryStream();
                    imgBase.Save(mergedImageStream, ImageFormat.Png);
                    mergedImageData = mergedImageStream.ToArray();
                    mergedImageStream.Close();
                }
            }
            return mergedImageData;
        }
Lukas
  • 2,765
  • 2
  • 28
  • 30
2

If you have the source arrays in an array itself you can use SelectMany:

var arrays = new[]{new[]{1, 2, 3}, new[]{4, 5, 6}};
var combined = arrays.SelectMany(a => a).ToArray();
foreach (var v in combined) Console.WriteLine(v);   

gives

1
2
3
4
5
6

Probably this is not the fastest method but might fit depending on usecase.

schoetbi
  • 10,981
  • 10
  • 50
  • 71
1

Here is a simple example using Array.CopyTo. I think that it answers your question and gives an example of CopyTo usage - I am always puzzled when I need to use this function because the help is a bit unclear - the index is the position in the destination array where inserting occurs.

int[] xSrc1 = new int[3] { 0, 1, 2 };
int[] xSrc2 = new int[5] { 3, 4, 5, 6 , 7 };

int[] xAll = new int[xSrc1.Length + xSrc2.Length];
xSrc1.CopyTo(xAll, 0);
xSrc2.CopyTo(xAll, xSrc1.Length);

I guess you can't get it much simpler.

pasx
  • 2,312
  • 26
  • 22
0
int [] SouceArray1 = new int[] {2,1,3};
int [] SourceArray2 = new int[] {4,5,6};
int [] targetArray = new int [SouceArray1.Length + SourceArray2.Length];
SouceArray1.CopyTo(targetArray,0);
SourceArray2.CopyTo(targetArray,SouceArray1.Length) ; 
foreach (int i in targetArray) Console.WriteLine(i + " ");  

Using the above code two Arrays can be easily merged.

vikasse
  • 445
  • 2
  • 8
  • 20
0

Created and extension method to handle null

public static class IEnumerableExtenions
{
    public static IEnumerable<T> UnionIfNotNull<T>(this IEnumerable<T> list1, IEnumerable<T> list2)
    {
        if (list1 != null && list2 != null)
            return list1.Union(list2);
        else if (list1 != null)
            return list1;
        else if (list2 != null)
            return list2;
        else return null;
    }
}
Lord Darth Vader
  • 1,775
  • 1
  • 15
  • 24
0

I'm assuming you're using your own array types as opposed to the built-in .NET arrays:

public string[] merge(input1, input2)
{
    string[] output = new string[input1.length + input2.length];
    for(int i = 0; i < output.length; i++)
    {
        if (i >= input1.length)
            output[i] = input2[i-input1.length];
        else
            output[i] = input1[i];
    }
    return output;
}

Another way of doing this would be using the built in ArrayList class.

public ArrayList merge(input1, input2)
{
    Arraylist output = new ArrayList();
    foreach(string val in input1)
        output.add(val);
    foreach(string val in input2)
        output.add(val);
    return output;
}

Both examples are C#.

takrl
  • 6,298
  • 3
  • 59
  • 67
apandit
  • 3,294
  • 1
  • 25
  • 32
0
string[] names1 = new string[] { "Ava", "Emma", "Olivia" };
string[] names2 = new string[] { "Olivia", "Sophia", "Emma" };
List<string> arr = new List<string>(names1.Length + names2.Length);
arr.AddRange(names1);
arr.AddRange(names2);
string[] result = arr.Distinct().ToArray();
foreach(string str in result)
{
    Console.WriteLine(str.ToString());
}

Console.ReadLine();
Dorin Baba
  • 996
  • 1
  • 9
  • 20
  • 1
    Please add further details to expand on your answer, such as working code or documentation citations. – Community Aug 26 '21 at 14:23
-1

This code will work for all cases:

int[] a1 ={3,4,5,6};
int[] a2 = {4,7,9};
int i = a1.Length-1;
int j = a2.Length-1;
int resultIndex=  i+j+1;
Array.Resize(ref a2, a1.Length +a2.Length);
while(resultIndex >=0)
{
    if(i != 0 && j !=0)
    {
        if(a1[i] > a2[j])
        {
            a2[resultIndex--] = a[i--];
        }
        else
        {
            a2[resultIndex--] = a[j--];
        }
    }
    else if(i>=0 && j<=0)
    { 
        a2[resultIndex--] = a[i--];
    }
    else if(j>=0 && i <=0)
    {
       a2[resultIndex--] = a[j--];
    }
}
atiquratik
  • 1,288
  • 3
  • 26
  • 33
  • Could you please add more description about the solution you provide? – abarisone Apr 12 '15 at 16:47
  • 1
    While this code snippet may solve the question, [including an explanation](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – gunr2171 Apr 12 '15 at 17:23
  • This appears to be a sorted merge, which while useful in its own right (mainly as part of a MergeSort recursive strategy), might be more than the OP was asking for. – Darrel Hoffman Jan 14 '19 at 14:26
  • While this solution works, having lot of techniques available since C# and VB.Net was introduced people may not prefer such solutions. – Sudhakar Chavali Dec 04 '19 at 16:04
-1

Simple code to join multiple arrays:

string[] arr1 = ...
string[] arr2 = ...
string[] arr3 = ...    
List<string> arr = new List<string>(arr1.Length + arr2.Length + arr3.Length);
arr.AddRange(arr1);
arr.AddRange(arr2);
arr.AddRange(arr3);
string[] result = arr.ToArray();
-1

This is another way to do this :)

public static void ArrayPush<T>(ref T[] table, object value)
{
    Array.Resize(ref table, table.Length + 1); // Resizing the array for the cloned length (+-) (+1)
    table.SetValue(value, table.Length - 1); // Setting the value for the new element
}

public static void MergeArrays<T>(ref T[] tableOne, T[] tableTwo) {
    foreach(var element in tableTwo) {
        ArrayPush(ref tableOne, element);
    }
}

Here is the snippet/example

Mondonno
  • 81
  • 10
-2

Try this:

ArrayLIst al = new ArrayList();
al.AddRange(array_1);
al.AddRange(array_2);
al.AddRange(array_3);
array_4 = al.ToArray();
Peter Mortensen
  • 30,030
  • 21
  • 100
  • 124
namco
  • 5,912
  • 17
  • 57
  • 83