Pregunta

¿Existe una función integrada en .NET 2.0 que tomará dos matrices y las fusionará en una sola?

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

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

¿Fue útil?

Solución

Si 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, puedes crear 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);

Más información sobre los métodos de matriz disponibles en MSDN.

Otros consejos

En C# 3.0 puedes usar LINQ Concat método para 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 no tienes 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.

Usar LINQ:

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

Tenga en cuenta que esto eliminará los duplicados.Si desea conservar duplicados, utilice Concat.

Si no desea eliminar duplicados, intente esto

Utilice LINQ:

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

Primero, asegúrese de preguntarse "¿Debería realmente usar una matriz aquí?".

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

Más fácil sería simplemente usar LINQ:

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

Primero convierta las matrices en listas y combínelas...Después de eso, simplemente convierta la lista nuevamente a una matriz :)

creo que puedes usar Matriz.Copiar para esto.Se necesita un índice de origen y un índice de destino, por lo que debería poder agregar una matriz a la otra.Si necesita algo más complejo que simplemente agregar uno al otro, es posible que esta no sea la herramienta adecuada para usted.

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

Personalmente, prefiero mis propias extensiones de idioma, que agrego o elimino a voluntad para crear prototipos rápidamente.

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 usar un personalizado IEnumerable Contenedor de tipos que almacena referencias/punteros de matrices pasadas y permite recorrer toda la colección como si fuera una matriz normal.(Útil en HPC, procesamiento de gráficos, renderizado de gráficos...)

Tu codigo:

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

Para ver el código completo y una versión genérica, consulte: https://gist.github.com/lsauer/7919764

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

Compilé este tipo de extensiones desde 2002, y muchos créditos van a personas útiles en CodeProject y 'Stackoverflow'.Los publicaré en breve y pondré el enlace aquí.

Todos ya han expresado su opinión, pero creo que esto es más legible que el enfoque de "usar 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, sólo se puede utilizar cuando se juntan 2 matrices.

En caso de que alguien más esté buscando cómo fusionar 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;
        }

Sólo para indicarlo como opción:si las matrices con las que está trabajando son de tipo primitivo: booleano (bool), Char, SByte, Byte, Int16 (corto), UInt16, Int32 (int), UInt32, Int64 (largo), UInt64, IntPtr, UIntPtr, Single , o Double – entonces podrías (¿o deberías?) intentar usar Buffer.BlockCopy.Según la página de MSDN para el Buffer clase:

Esta clase proporciona un mejor rendimiento para manipular tipos primitivos que métodos similares en el Sistema.Array clase.

Usando el ejemplo de C# 2.0 de @OwenP respuesta Como punto de partida, funcionaría de la siguiente manera:

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 el Array.Copy que usó @OwenP, pero esto debería ser más rápido (aunque sea un poco).

A continuación se muestra un ejemplo sencillo que utiliza Array.CopyTo.Creo que responde a su pregunta y ofrece un ejemplo del uso de CopyTo. Siempre me desconcierta cuando necesito usar esta función porque la ayuda no es un poco clara: el índice es la posición en la matriz de destino donde se produce 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 puedes hacerlo mucho más simple.

Necesitaba una solución para combinar un número desconocido de matrices.

Me sorprende que nadie más haya proporcionado una solución usando SelectMany con params.

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

Si no desea elementos distintos, simplemente elimine los distintos.

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

Nota:Definitivamente no hay garantía de realizar pedidos cuando se utiliza distinto.

Esto es lo que se me ocurrió.Funciona para un número variable de matrices.

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 }

Supongo que está utilizando sus propios tipos de matrices en lugar de las matrices .NET integradas:

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 hacerlo sería utilizar la clase ArrayList integrada.

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#.

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

Usando el código anterior se pueden fusionar fácilmente dos matrices.

Método creado y de extensión para manejar nulos.

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

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

Prueba esto:

ArrayLIst al = new ArrayList();
al.AddRange(array_1);
al.AddRange(array_2);
al.AddRange(array_3);
array_4 = al.ToArray();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top