Domanda

Esiste una funzione incorporata in .NET 2.0 che richiederà due array e li unirà in un unico array?

Gli array sono entrambi dello stesso tipo.Ottengo questi array da una funzione ampiamente utilizzata all'interno della mia base di codice e non riesco a modificare la funzione per restituire i dati in un formato diverso.

Sto cercando di evitare di scrivere la mia funzione per ottenere questo risultato, se possibile.

È stato utile?

Soluzione

Se puoi manipolare uno degli array, puoi ridimensionarlo prima di eseguire 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);

Altrimenti puoi creare un nuovo array

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

Ulteriori informazioni sui metodi Array disponibili su MSDN.

Altri suggerimenti

In C# 3.0 puoi utilizzare LINQ Concat metodo per ottenere questo risultato facilmente:

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

In C# 2.0 non hai un modo così diretto, ma Array.Copy è probabilmente la soluzione migliore:

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

Questo potrebbe essere facilmente utilizzato per implementare la tua versione di Concat.

Utilizzo LINQ:

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

Tieni presente che questo rimuoverà i duplicati.Se vuoi conservare i duplicati, usa Concat.

Se non vuoi rimuovere i duplicati, prova questo

Utilizza LINQ:

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

Innanzitutto, assicurati di porsi la domanda "Dovrei davvero utilizzare un array qui"?

A meno che tu non stia costruendo qualcosa in cui la velocità è della massima importanza, un elenco digitato, come List<int> è probabilmente la strada da percorrere.L'unica volta che utilizzo gli array è per gli array di byte quando invio materiale sulla rete.A parte questo, non li tocco mai.

Sarebbe più facile semplicemente usarlo LINQ:

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

Per prima cosa converti gli array in elenchi e uniscili ...Dopodiché riconverti l'elenco in un array :)

Penso che tu possa usare Array.Copia per questo.Richiede un indice di origine e un indice di destinazione, quindi dovresti essere in grado di aggiungere un array all'altro.Se hai bisogno di qualcosa di più complesso rispetto alla semplice aggiunta di uno all'altro, questo potrebbe non essere lo strumento giusto per te.

Supponendo che l'array di destinazione abbia spazio sufficiente, Array.Copy() funzionerà.Potresti anche provare a utilizzare a List<T> e il suo .AddRange() metodo.

Personalmente, preferisco le mie estensioni linguistiche, che aggiungo o rimuovo a piacimento per una rapida prototipazione.

Di seguito è riportato un esempio per le stringhe.

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

È molto più veloce di LINQ e Concat.Ancora più veloce, sta usando un custom IEnumerable Type-wrapper che memorizza riferimenti/puntatori di array passati e consente il looping sull'intera raccolta come se fosse un normale array.(Utile in HPC, elaborazione grafica, rendering grafico...)

Il tuo codice:

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

Per l'intero codice e una versione generica vedere: https://gist.github.com/lsauer/7919764

Nota: Ciò restituisce un oggetto IEnumerable non esteso.Restituire un oggetto esteso è un po' più lento.

Ho compilato tali estensioni dal 2002, e molti crediti sono andati a persone utili su CodeProject e "Stackoverflow".Li pubblicherò a breve e inserirò il collegamento qui.

Tutti hanno già detto la loro, ma penso che questo sia più leggibile rispetto all'approccio "usa come metodo di estensione":

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

Tuttavia può essere utilizzato solo quando si uniscono 2 array.

Nel caso in cui qualcun altro stia cercando come unire due array di byte di immagine:

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

Giusto per averlo annotato come opzione:se gli array con cui stai lavorando sono di tipo primitivo: Boolean (bool), Char, SByte, Byte, Int16 (short), UInt16, Int32 (int), UInt32, Int64 (long), UInt64, IntPtr, UIntPtr, Single , o Double: allora potresti (o dovresti?) provare a utilizzare Buffer.BlockCopy.Secondo la pagina MSDN per il Respingente classe:

Questa classe fornisce prestazioni migliori per la manipolazione di tipi primitivi rispetto a metodi simili in System.Array classe.

Utilizzando l'esempio C# 2.0 di @OwenP's risposta come punto di partenza, funzionerebbe come segue:

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

Non c'è quasi alcuna differenza nella sintassi tra Buffer.BlockCopy e il Array.Copy utilizzato da @OwenP, ma dovrebbe essere più veloce (anche se solo leggermente).

Ecco un semplice esempio che utilizza Array.CopyTo.Penso che risponda alla tua domanda e fornisca un esempio di utilizzo di CopyTo - Sono sempre perplesso quando devo usare questa funzione perché la guida è un po' poco chiara - l'indice è la posizione nell'array di destinazione in cui avviene l'inserimento.

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

Immagino che non sia possibile renderlo molto più semplice.

Avevo bisogno di una soluzione per combinare un numero imprecisato di array.

Sorpreso che nessun altro abbia fornito una soluzione utilizzando SelectMany con params.

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

Se non desideri elementi distinti, rimuovi semplicemente distinti.

 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:Non c'è assolutamente alcuna garanzia di ordine quando si utilizza distinto.

Questo è quello che mi è venuto in mente.Funziona per un numero variabile di array.

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 }

Presumo che tu stia utilizzando i tuoi tipi di array anziché gli array .NET integrati:

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

Un altro modo per farlo sarebbe utilizzare la classe ArrayList incorporata.

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

Entrambi gli esempi sono 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 il codice sopra due array possono essere facilmente uniti.

Metodo creato ed estensione per gestire null

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

Questo codice funzionerà per tutti i casi:

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

Prova questo:

ArrayLIst al = new ArrayList();
al.AddRange(array_1);
al.AddRange(array_2);
al.AddRange(array_3);
array_4 = al.ToArray();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top