2008-09-12 21 views
167

¿Hay una función incorporada en .NET 2.0 que tomará dos matrices y las fusionará en una matriz?Fusionando dos arrays en .NET

Las matrices son del mismo tipo. Obtengo estas matrices de una función ampliamente utilizada dentro de mi base de códigos y no puedo modificar la función para devolver los datos en un formato diferente.

Estoy tratando de evitar escribir mi propia función para lograr esto si es posible.

Respuesta

88

Si se puede manipular una de las matrices, puede cambiar su tamaño antes de realizar la copia:

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

De lo contrario, se puede hacer una nueva matriz

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.

+1

¿Qué pasa con .NET 4.0, ¿hay noticias? – Shimmy

+2

Tenga en cuenta que 'Array.Resize' en realidad no cambia el tamaño de la matriz, sino que la copia. Es por eso que el primer parámetro es by-ref (lo que significa que su primer código probablemente no compilará). – CodesInChaos

+2

Me gustaría tirar tu primer pedazo de código. No ofrece una ventaja, y es más difícil de leer IMO. – CodesInChaos

7

Creo que puede usar Array.Copy para esto. Toma un índice de origen y un índice de destino, por lo que debería poder agregar una matriz a la otra. Si necesita ir más complejo que solo agregar uno al otro, puede que esta no sea la herramienta adecuada para usted.

5

Suponiendo que la matriz de destino tiene suficiente espacio, Array.Copy() funcionará. También puede intentar usar un List<T> y su método .AddRange().

0

Estoy asumiendo que usted está utilizando sus propios tipos de matriz en lugar de la incorporada en matrices .NET:

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

Otra forma de hacer esto sería utilizando el construido en la clase ArrayList.

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

Ambos ejemplos son C#.

8

Primero, asegúrese de hacerse la pregunta "¿De verdad debería usar una matriz aquí?"

A menos que esté creando algo donde la velocidad es de la mayor importancia, una Lista tipeada, como List<int> es probablemente el camino a seguir. La única vez que uso matrices son para matrices de bytes cuando envío cosas a través de la red. Aparte de eso, nunca los toco.

+0

Big +1 aquí. Tenga en cuenta que la mejor práctica es evitar la exposición 'List ' en API públicas: http://blogs.msdn.com/b/kcwalina/archive/2005/09/26/474010.aspx – TrueWill

343

En C# 3.0 se puede utilizar el método de LINQ Concat de lograr esto fácilmente:

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

En C# 2.0 ustedes no tienen una forma tan directa, pero Array.Copy es probablemente la mejor solución:

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

Esto podría usarse fácilmente para implementar su propia versión de Concat.

+1

Me gusta la implementación de LINQ. Realmente necesito dar el salto y entrar en LINQ pronto ... – GEOCHET

+1

Rico, la mejor parte acerca de la implementación de LINQ no solo es conciso, también es tan eficiente como la versión 2.0, ya que funciona en contra de IEnumerable. –

+7

+1, .Concat realmente me ayudó. – tsilb

-1

Prueba esto:

ArrayLIst al = new ArrayList(); 
al.AddRange(array_1); 
al.AddRange(array_2); 
al.AddRange(array_3); 
array_4 = al.ToArray(); 
1

Aquí está un ejemplo sencillo usando Array.CopyTo. Creo que responde su pregunta y da un ejemplo de uso de CopyTo. Siempre me deja perplejo cuando necesito usar esta función porque la ayuda no está clara: el índice es la posición en la matriz de destino donde ocurre la inserción.

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

Supongo que no se puede conseguir mucho más simple.

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

Utilizando el código anterior, dos matrices se pueden combinar fácilmente.

4

Personalmente, prefiero mis propias extensiones de idioma, que agrego o quito a voluntad para la creación rápida de prototipos.

A continuación se muestra un ejemplo de cadenas.

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

Es mucho más rápido que LINQ y Concat. Más rápido aún, es el uso de un contenedor de tipo personalizado IEnumerable que almacena referencias/punteros de matrices pasadas y permite el bucle sobre toda la colección como si fuera una matriz normal. (Útil en HPC, de procesamiento gráfico, gráficos hacen ...)

Su Código:

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

Para todo el código y ver una versión genéricos: https://gist.github.com/lsauer/7919764

Nota: Este devuelve un objeto IEnumerable no extendido. Devolver un objeto extendido es un poco más lento.

Recopilé tales extensiones desde 2002, con un montón de créditos para personas útiles en CodeProject y 'Stackoverflow'. Los lanzaré en breve y pondré el enlace aquí.

42

Uso LINQ:

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

PRECAUCIÓN: Union eliminará duplicados. – Yogee

+1

@Yogee, fácil de recordar, ya que es como en SQL y también la nomenclatura está conectada con la teoría de conjuntos. –

+5

, ya que eliminará duplicados, nunca puede ser una respuesta adecuada. –

8

más fácil sólo sería utilizar LINQ:

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

Primera convertir las matrices para las listas y unirlos ... Después de eso, convertir la lista de nuevo a una array :)

2

En caso de que alguien más esté buscando cómo combinar dos matrices de bytes de imágenes:

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

Este código funcionará para todos los casos:

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--]; 
    } 
} 
+0

¿Podría agregar más descripciones sobre la solución que proporciona? – abarisone

+1

Si bien este fragmento de código puede resolver la pregunta, [incluyendo una explicación] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) realmente ayuda a mejorar la calidad de su publicación.Recuerde que usted está respondiendo la pregunta a los lectores en el futuro, y es posible que esas personas no sepan los motivos de su sugerencia de código. – gunr2171

4

Todo el mundo ya ha dado su opinión, pero creo que esto más fácil de leer que el enfoque de "utilizar como método de extensión":

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

Sin embargo, solo se puede usar al reunir 2 matrices.

+0

Esto no funcionó para mí con 2 matrices de cadena. – JayJay

1

Sólo para tener que señalar como una opción: si las matrices que se está trabajando son de un tipo primitivo – booleana (bool), Char, SByte, Byte, Int16 (corto), UInt16, Int32 (int), UInt32 , Int64 (largo), UInt64, IntPtr, UIntPtr, Simple o Doble –, entonces podría (¿o debería?) Intentar usar Buffer.BlockCopy.De acuerdo con la página de MSDN para la clase Buffer:

Esta clase proporciona un mejor rendimiento para la manipulación de los tipos primitivos que los métodos similares en la clase System.Array.

Usando el ejemplo C# 2.0 desde de answer como punto de partida @ OwenP, que funcionaría como sigue:

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

Apenas hay diferencia en la sintaxis entre Buffer.BlockCopy y la Array.Copy que @OwenP utiliza, pero esto debería ser más rápido (aunque solo sea levemente).

9

Si no desea eliminar duplicados, entonces prueba este

uso de LINQ:

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

Creado y método de extensión para manejar nula

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