Come concatenare due array in C #?

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

In questo momento io uso

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

C’è un metodo più semplice o più efficiente?

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

Prova questo:

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

Potresti scrivere un metodo di estensione:

 public static T[] Concat(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(ref x, x.Length + y.Length); Array.Copy(y, 0, x, oldLen, y.Length); return x; } 

Poi:

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

Ho optato per una soluzione più generale che consente di concatenare un insieme arbitrario di matrici unidimensionali dello stesso tipo. (Stavo concatenando 3+ alla volta.)

La mia funzione:

  public static T[] ConcatArrays(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; } 

E l'uso:

  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} 

Questo è:

 using System.Linq; int[] array1 = { 1, 3, 5 }; int[] array2 = { 0, 2, 4 }; // Concatenate array1 and array2. var result1 = array1.Concat(array2); 

È ansible interrompere la chiamata ToArray () alla fine. C’è una ragione per cui devi essere un array dopo la chiamata a Concat?

Chiamare Concat crea un iteratore su entrambi gli array. Non crea un nuovo array in modo da non aver usato più memoria per un nuovo array. Quando si chiama ToArray, si crea effettivamente un nuovo array e si acquisisce la memoria per il nuovo array.

Quindi, se hai solo bisogno di scorrere facilmente entrambi, chiama semplicemente Concat.

So che l’OP era solo leggermente curiosa delle prestazioni. Quegli array più grandi possono ottenere un risultato diverso (vedi @kurdishTree). E che di solito non importa (@ jordan.peoples). Nondimeno, ero curioso e quindi ho perso la testa (come stava spiegando @TigerShark) … Voglio dire che ho scritto un semplice test basato sulla domanda originale …. e tutte le risposte ….

 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 list = new List(); 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 targetList = new List(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(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(ref x, x.Length + y.Length); Array.Copy(y, 0, x, oldLen, y.Length); return x; } public static T[] ConcatArrays(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(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(params T[][] arrays) { return (from array in arrays from arr in array select arr).ToArray(); } public static T[] ConcatArraysLambda(params T[][] arrays) { return arrays.SelectMany(array => array.Select(arr => arr)).ToArray(); } } } 

Il risultato è stato:

inserisci la descrizione dell'immagine qui

Tira le tue vittorie.

Stai attento con il metodo Concat . Il post Array Concatenation in C # spiega che:

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

Sarà inefficiente per i grandi array. Ciò significa che il metodo Concat è solo per array di dimensioni meduim (fino a 10000 elementi).

 public static T[] Concat(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; } 

Risposta in ritardo :-).

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

Più efficiente (più veloce) usare Buffer.BlockCopy su 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)); 

Ho scritto un semplice programma di test che “scalda il jitter”, compilato in modalità di rilascio e eseguito senza un debugger collegato, sulla mia macchina.

Per 10.000.000 iterazioni dell’esempio nella domanda

Concat ha preso 3088ms

CopyTo ha richiesto 1079 ms

BlockCopy ha preso 603 ms

Se modifico gli array di test su due sequenze da 0 a 99, ottengo risultati simili a questo,

Concat ha preso 45945 ms

CopyTo ha richiesto 2230ms

BlockCopy ha preso 1689ms

Da questi risultati posso affermare che i metodi CopyTo e BlockCopy sono significativamente più efficienti di Concat e inoltre, se le prestazioni sono un objective, BlockCopy ha valore su CopyTo .

Per evitare questa risposta, se le prestazioni non contano, o ci saranno poche iterazioni, scegli il metodo che trovi più semplice. Buffer.BlockCopy offre alcune utilità per la conversione del tipo oltre lo scopo di questa domanda.

Puoi farlo nel modo in cui ti sei indirizzato, o se vuoi davvero farne un manuale puoi farlo da solo:

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

La struttura più efficiente in termini di RAM (e CPU) per contenere l’array combinato sarebbe una class speciale che implementa IEnumerable (o se si desidera persino deriva dalla matrice) e si collega internamente agli array originali per leggere i valori. AFAIK Concat fa proprio questo.

Nel tuo codice di esempio puoi comunque omettere il .ToArray (), il che lo renderebbe più efficiente.

Quello che devi ricordare è che quando si utilizza LINQ si sta utilizzando l’esecuzione ritardata. Gli altri metodi qui descritti funzionano perfettamente, ma vengono eseguiti immediatamente. Inoltre la funzione Concat () è probabilmente ottimizzata in modi che non è ansible fare da soli (chiamate alle API interne, chiamate al sistema operativo ecc.). Ad ogni modo, a meno che tu non abbia davvero bisogno di provare e ottimizzare, sei attualmente sulla tua strada verso “la radice di tutti i mali”;)

Ho trovato un’elegante soluzione a una linea che usa espressioni LINQ o Lambda , entrambe funzionano allo stesso modo (LINQ viene convertito in Lambda quando il programma è compilato). La soluzione funziona per qualsiasi tipo di array e per qualsiasi numero di array.

Utilizzando LINQ:

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

Utilizzando Lambda:

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

Ho fornito entrambi per la preferenza di uno. Performance wise Le soluzioni di @Sergey Shteyn o @ deepee1 sono un po ‘più veloci, l’espressione Lambda è la più lenta. Il tempo impiegato dipende dal tipo (i) degli elementi dell’array, ma a meno che non ci siano milioni di chiamate, non c’è differenza significativa tra i metodi.

Prova quanto segue:

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

Ci scusiamo per rianimare un thread vecchio, ma come su questo:

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

Quindi nel tuo codice:

 int[] x={1, 2, 3}; int[] y={4, 5, 6}; var z=Merge(x, y); // 'z' is IEnumerable var za=z.ToArray(); // 'za' is int[] 

Fino a quando non chiami .ToArray() , .ToList() o .ToDictionary(...) , la memoria non è allocata, sei libero di “build la tua query” e chiama uno di questi tre per eseguirlo o semplicemente vai attraverso tutti loro utilizzando la clausola foreach (var i in z){...} che restituisce un elemento alla volta dal yield return t; sopra…

La suddetta funzione può essere trasformata in un’estensione come segue:

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

Quindi nel codice, puoi fare qualcosa come:

 int[] x1={1, 2, 3}; int[] x2={4, 5, 6}; int[] x3={7, 8}; var z=x1.Merge(x2).Merge(x3); // 'z' is IEnumerable var za=z.ToArray(); // 'za' is int[] 

Il resto è lo stesso di prima.

Un altro miglioramento sarebbe la modifica di T[] in IEnumerable (quindi i params T[][] diventerebbero i params IEnumerable[] ) per fare in modo che queste funzioni accettino più di semplici matrici.

Spero che questo ti aiuti.

Per int [] quello che hai fatto mi sembra buono. la risposta di astander funzionerebbe bene anche per List .

Per array più piccoli <10000 elementi:

 using System.Linq; int firstArray = {5,4,2}; int secondArray = {3,2,1}; int[] result = firstArray.ToList().Concat(secondArray.ToList()).toArray(); 
 static class Extensions { public static T[] Concat(this T[] array1, params T[] array2) { return ConcatArray(array1, array2); } public static T[] ConcatArray(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; } } 

Penso che la soluzione di cui sopra sia più generale e più leggera delle altre che ho visto qui. È più generale perché non limita la concatenazione solo per due array ed è più leggero perché non usa LINQ né List.

Nota che la soluzione è concisa e la generalità aggiunta non aggiunge un sovraccarico di runtime significativo.

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

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