example concatenate array c#

concatenate - join string array c#



¿Cómo concatenar dos matrices en C#? (22)

Aquí está mi respuesta:

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

Este método se puede utilizar en el nivel de inicialización, por ejemplo, para definir una concatenación estática de matrices estáticas:

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

Sin embargo, viene con dos advertencias que debe tener en cuenta:

  • El método Concat crea un iterador sobre ambas matrices: no crea una nueva matriz, por lo que es eficiente en términos de la memoria utilizada: sin embargo, el ToArray posterior ToArray dicha ventaja, ya que en realidad creará una nueva matriz y ocupará la memoria para la nueva matriz.
  • Como dijo @Jodrell, Concat sería bastante ineficiente para arreglos grandes: solo debería usarse para arreglos de tamaño mediano.

Si apuntar hacia el desempeño es un deber, se puede usar el siguiente método:

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

O (para los fanáticos de una sola línea):

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

Aunque el último método es mucho más elegante, el primero es definitivamente mejor para el rendimiento.

Para obtener información adicional, consulte esta publicación en mi blog.

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

-

Ahora mismo uso

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

¿Existe un método más fácil o más eficiente?


Eso es todo:

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


He encontrado una solución elegante de una línea usando LINQ o expresión Lambda , ambas funcionan igual (LINQ se convierte a Lambda cuando se compila el programa). La solución funciona para cualquier tipo de matriz y para cualquier número de matrices.

Utilizando LINQ:

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

Usando Lambda:

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

He proporcionado ambos para su preferencia. En cuanto al rendimiento, las soluciones de @Sergey Shteyn o @deepee1''s son un poco más rápidas, y la expresión Lambda es la más lenta. El tiempo empleado depende de los tipos de elementos de la matriz, pero a menos que haya millones de llamadas, no hay una diferencia significativa entre los métodos.


Intenta lo siguiente:

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


La estructura más eficiente en términos de RAM (y CPU) para mantener la matriz combinada sería una clase especial que implemente IEnumerable (o si lo desea se deriva de la matriz) y se vincule internamente a las matrices originales para leer los valores. AFAIK Concat hace justamente eso.

Sin embargo, en su código de muestra podría omitir .ToArray (), lo que lo haría más eficiente.


Lo que debe recordar es que cuando usa LINQ está utilizando la ejecución diferida. Los otros métodos descritos aquí funcionan perfectamente, pero se ejecutan inmediatamente. Además, la función Concat () está probablemente optimizada en formas que no puede hacerlo usted mismo (llamadas a API internas, llamadas a sistemas operativos, etc.). De todos modos, a menos que realmente necesites intentar optimizar, estás actualmente en tu camino hacia "la raíz de todo mal";)


Más eficiente (más rápido) de usar Buffer.BlockCopy sobre 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));

Escribí un programa de prueba simple que "calienta el Jitter", compilado en modo de lanzamiento y lo ejecuté sin un depurador adjunto, en mi máquina.

Para 10,000,000 iteraciones del ejemplo en la pregunta.

Concat tomó 3088ms

CopyTo tomó 1079ms

BlockCopy tomó 603ms

Si modifico las matrices de prueba a dos secuencias de 0 a 99, obtengo resultados similares a estos.

Concat tomó 45945ms

CopyTo tomó 2230ms.

BlockCopy tomó 1689ms

A partir de estos resultados, puedo afirmar que los métodos CopyTo y BlockCopy son significativamente más eficientes que Concat y, además, si el rendimiento es un objetivo, BlockCopy tiene valor sobre CopyTo .

Para evitar esta respuesta, si el rendimiento no importa, o habrá pocas iteraciones, elija el método que le resulte más fácil. Buffer.BlockCopy ofrece alguna utilidad para la conversión de tipos más allá del alcance de esta pregunta.


Me decidí por una solución de propósito más general que permite concatenar un conjunto arbitrario de arreglos unidimensionales del mismo tipo. (Estaba concatenando 3+ a la vez.)

Mi función:

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

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


Para int [] lo que has hecho me parece bien. astander''s respuesta astander''s también funcionaría bien para la List<int> .


Para matrices más pequeñas <10000 elementos:

using System.Linq; int firstArray = {5,4,2}; int secondArray = {3,2,1}; int[] result = firstArray.ToList().Concat(secondArray.ToList()).toArray();


Podrías escribir un método de extensión:

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

Entonces:

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


Prueba esto:

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


Puede hacerlo de la forma en que se ha referido, o si desea obtener un manual realmente puede hacer su propio bucle:

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


Puedes quitar la llamada ToArray () del final. ¿Hay alguna razón por la que necesite que sea una matriz después de la llamada a Concat?

Al llamar a Concat se crea un iterador sobre ambos arreglos. No crea una nueva matriz, por lo que no ha utilizado más memoria para una nueva matriz. Cuando llama a ToArray, en realidad crea una nueva matriz y ocupa la memoria para la nueva matriz.

Entonces, si solo necesita iterar fácilmente sobre ambos, simplemente llame a Concat.


Respuesta tardía :-).

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


Sé que el OP solo tenía un poco de curiosidad por el rendimiento. Que los arreglos más grandes pueden obtener un resultado diferente (vea @kurdishTree). Y que por lo general no importa (@jordan.peoples). Sin embargo, sentí curiosidad y, por lo tanto, perdí la cabeza (como lo explicaba @TigerShark) ... Quiero decir que escribí una prueba simple basada en la pregunta original ... y todas las respuestas ...

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

El resultado fue:

Roll sus propias victorias.


Siento revivir un hilo viejo, pero ¿qué tal esto?

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

Luego en su código:

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

Hasta que llame a .ToArray() , .ToList() o .ToDictionary(...) , la memoria no está asignada, puede "construir su consulta" y llamar a uno de esos tres para ejecutarla o simplemente ir a través de todos ellos, usando la cláusula foreach (var i in z){...} que devuelve un artículo a la vez desde el yield return t; encima...

La función anterior se puede convertir en una extensión de la siguiente manera:

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

Así que en el código, puedes hacer algo como:

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

El resto es el mismo que antes.

Otra mejora a esto sería cambiar T[] a IEnumerable<T> (por lo que los params T[][] se convertirían en params IEnumerable<T>[] ) para que estas funciones acepten más que solo arreglos.

Espero que esto ayude.


Ten cuidado con el método Concat . El post Array Concatenation in C # explica que:

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

Será ineficiente para arreglos grandes. Eso significa que el método Concat es solo para arreglos de tamaño mediano (hasta 10000 elementos).


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

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


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


static class Extensions { public static T[] Concat<T>(this T[] array1, params T[] array2) { return 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; } }

Creo que la solución anterior es más general y más liviana que las otras que vi aquí. Es más general porque no limita la concatenación solo para dos matrices y es más ligero porque no usa LINQ ni List.

Tenga en cuenta que la solución es concisa y la generalidad agregada no agrega una sobrecarga significativa en el tiempo de ejecución.


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