Como faço para concatenar duas matrizes em 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 })); 

Agora eu uso

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

Existe um método mais fácil ou mais eficiente?

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

Tente isto:

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

Você poderia escrever um método de extensão:

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

Então:

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

Estabeleci uma solução de propósito geral que permite a concatenação de um conjunto arbitrário de matrizes unidimensionais do mesmo tipo. (Eu estava concatenando 3+ de cada vez.)

Minha function:

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

É isso:

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

Você pode tirar a chamada ToArray () do final. Existe uma razão pela qual você precisa que seja um array após a chamada para o Concat?

Calling Concat cria um iterador em ambos os arrays. Ele não cria uma nova matriz, portanto você não usou mais memory para uma nova matriz. Quando você chama ToArray, você cria uma nova matriz e ocupa a memory da nova matriz.

Então, se você só precisa facilmente iterar sobre ambos, basta chamar Concat.

Eu sei que o OP estava apenas ligeiramente curioso sobre o desempenho. Que matrizes maiores podem obter um resultado diferente (consulte @kurdishTree). E isso geralmente não importa (@ jordan.peoples). No entanto, eu estava curioso e, portanto, perdi a cabeça (como o @TigerShark estava explicando) …. quero dizer que eu escrevi um teste simples baseado na pergunta original … e todas as respostas ….

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

O resultado foi:

insira a descrição da imagem aqui

Jogue suas próprias vitórias.

Tenha cuidado com o método Concat . O post Array Concatenation in C # explica que:

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

Será ineficiente para grandes matrizes. Isso significa que o método Concat é apenas para matrizes de tamanho médio (até 10000 elementos).

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

Resposta atrasada :-).

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

Mais eficiente (mais rápido) para usar o 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)); 

Eu escrevi um programa de teste simples que “aquece o Jitter”, compilado no modo de liberação e o executei sem um depurador anexado, na minha máquina.

Para 10.000.000 iterações do exemplo na questão

Concat levou 3088ms

CopyTo levou 1079ms

BlockCopy levou 603ms

Se eu alterar as matrizes de teste para duas seqüências de 0 a 99, então obtenho resultados semelhantes a isso,

Concat levou 45945ms

CopyTo levou 2230ms

BlockCopy levou 1689ms

A partir desses resultados, posso afirmar que os methods CopyTo e BlockCopy são significativamente mais eficientes do que o Concat e, além disso, se o desempenho for uma meta, o BlockCopy valor sobre CopyTo .

Para evitar essa resposta, se o desempenho não for importante ou se houver poucas iterações, escolha o método que você achar mais fácil. Buffer.BlockCopy oferece algum utilitário para conversão de tipo além do escopo desta questão.

Você pode fazer do jeito que você se referiu, ou se você quiser ser realmente manual, você pode rolar seu próprio 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]; 

A estrutura mais eficiente em termos de RAM (e CPU) para manter a matriz combinada seria uma class especial que implementa IEnumerable (ou, se você quiser, ainda deriva de Array) e links internamente para as matrizes originais para ler os valores. AFAIK Concat faz exatamente isso.

No seu código de exemplo, você poderia omitir o .ToArray (), o que o tornaria mais eficiente.

O que você precisa lembrar é que, ao usar o LINQ, você está utilizando a execução atrasada. Os outros methods descritos aqui funcionam perfeitamente, mas são executados imediatamente. Além disso, a function Concat () provavelmente é otimizada de maneiras que você não pode fazer sozinho (chamadas para APIs internas, chamadas de SO, etc.). De qualquer forma, a menos que você realmente precise tentar e otimizar, você está atualmente no seu caminho para “a raiz de todo mal”;)

Eu encontrei uma solução elegante de uma linha usando a expressão LINQ ou Lambda , ambas funcionam da mesma forma (o LINQ é convertido para o Lambda quando o programa é compilado). A solução funciona para qualquer tipo de matriz e para qualquer número de matrizes.

Usando o LINQ:

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

Usando Lambda:

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

Eu forneci tanto para a preferência de alguém. As soluções do @Sergey Shteyn ou @ deepee1 do desempenho são um pouco mais rápidas, a expressão do Lambda é a mais lenta. O tempo gasto depende do (s) tipo (s) de elementos da matriz, mas, a menos que haja milhões de chamadas, não há diferença significativa entre os methods.

Tente o seguinte:

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

Desculpe por reviver um thread antigo, mas e quanto a isso:

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

Então, no seu código:

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

Até você chamar .ToArray() , .ToList() ou .ToDictionary(...) , a memory não está alocada, você está livre para “construir sua consulta” e pode chamar um desses três para executá-lo ou simplesmente ir através de todos eles usando a cláusula foreach (var i in z){...} que retorna um item de cada vez do yield return t; acima…

A function acima pode ser feita em uma extensão da seguinte maneira:

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

Então, no código, você pode fazer 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 var za=z.ToArray(); // 'za' is int[] 

O resto é o mesmo de antes.

Uma outra melhoria para isso seria mudar T[] para IEnumerable (para que os params T[][] se tornassem params IEnumerable[] ) para fazer com que essas funções aceitassem mais do que apenas matrizes.

Espero que isto ajude.

Para int [] o que você fez parece ser bom para mim. resposta do astander também funcionaria bem para List .

Para matrizes menores <10000 elementos:

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

Eu acho que a solução acima é mais geral e mais leve que as outras que vi aqui. É mais geral porque não limita a concatenação para apenas dois arrays e é mais clara porque não usa o LINQ nem o List.

Observe que a solução é concisa e a generalidade adicionada não adiciona uma sobrecarga de tempo de execução significativa.

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

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