Question

Existe-t-il une fonction intégrée dans .NET 2.0 qui prendra deux tableaux et les fusionnera en un seul tableau ?

Les tableaux sont tous deux du même type.J'obtiens ces tableaux à partir d'une fonction largement utilisée dans ma base de code et je ne peux pas modifier la fonction pour renvoyer les données dans un format différent.

Je cherche à éviter d'écrire ma propre fonction pour y parvenir si possible.

Était-ce utile?

La solution

Si vous pouvez manipuler l'un des tableaux, vous pouvez le redimensionner avant d'effectuer la copie :

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

Sinon, vous pouvez créer un nouveau tableau

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

En savoir plus sur les méthodes Array disponibles sur MSDN.

Autres conseils

En C# 3.0, vous pouvez utiliser LINQ Concaténer méthode pour y parvenir facilement:

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

En C# 2.0, vous ne disposez pas d'un moyen aussi direct, mais Array.Copy est probablement la meilleure solution :

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

Cela pourrait facilement être utilisé pour implémenter votre propre version de Concat.

Utiliser LINQ:

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

Gardez à l’esprit que cela supprimera les doublons.Si vous souhaitez conserver les doublons, utilisez Concat.

Si vous ne souhaitez pas supprimer les doublons, essayez ceci

Utilisez LINQ :

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

Tout d’abord, assurez-vous de vous poser la question « Dois-je vraiment utiliser un tableau ici » ?

À moins que vous ne construisiez quelque chose où la vitesse est de la plus haute importance, une liste dactylographiée, comme List<int> est probablement la voie à suivre.La seule fois où j'utilise des tableaux, c'est pour les tableaux d'octets lors de l'envoi de données sur le réseau.A part ça, je ne les touche jamais.

Plus simple serait simplement d'utiliser LINQ:

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

Convertissez d’abord les tableaux en listes et fusionnez-les…Après cela, reconvertissez simplement la liste en tableau :)

Je pense que tu peux utiliser Tableau.Copie pour ça.Il faut un index source et un index de destination, vous devriez donc pouvoir ajouter un tableau à l'autre.Si vous avez besoin d'aller plus complexe que simplement ajouter l'un à l'autre, cet outil n'est peut-être pas le bon pour vous.

En supposant que le tableau de destination dispose de suffisamment d'espace, Array.Copy() marchera.Vous pouvez également essayer d'utiliser un List<T> et son .AddRange() méthode.

Personnellement, je préfère mes propres extensions de langage, que j'ajoute ou supprime à volonté pour un prototypage rapide.

Voici un exemple de chaînes.

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

C'est beaucoup plus rapide que LINQ et Concat.Plus rapide encore, utilise un personnalisé IEnumerable Type-wrapper qui stocke les références/pointeurs des tableaux passés et permet de parcourir toute la collection comme s'il s'agissait d'un tableau normal.(Utile en HPC, traitement graphique, rendu graphique...)

Votre code:

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

Pour le code complet et une version générique, voir : https://gist.github.com/lsauer/7919764

Note: Cela renvoie un objet IEnumerable non étendu.Retourner un objet étendu est un peu plus lent.

J'ai compilé de telles extensions depuis 2002, avec de nombreux crédits allant à des personnes utiles sur CodeProject et « Stackoverflow ».Je les publierai sous peu et mettrai le lien ici.

Tout le monde a déjà eu son mot à dire mais je pense que cela est plus lisible que l'approche "utiliser comme méthode d'extension":

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

Cependant il ne peut être utilisé que lors du regroupement de 2 tableaux.

Au cas où quelqu'un d'autre chercherait comment fusionner deux tableaux d'octets d'image :

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

Juste pour le noter en option :si les tableaux avec lesquels vous travaillez sont de type primitif – Boolean (bool), Char, SByte, Byte, Int16 (short), UInt16, Int32 (int), UInt32, Int64 (long), UInt64, IntPtr, UIntPtr, Single , ou Double – alors vous pourriez (ou devriez ?) essayer d’utiliser Buffer.BlockCopy.Selon la page MSDN pour le Tampon classe:

Cette classe offre de meilleures performances pour manipuler les types primitifs que les méthodes similaires du Système.Array classe.

Utilisation de l'exemple C# 2.0 de @OwenP répondre comme point de départ, cela fonctionnerait comme suit :

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

Il n'y a pratiquement aucune différence de syntaxe entre Buffer.BlockCopy et le Array.Copy que @OwenP a utilisé, mais cela devrait être plus rapide (même si ce n'est que légèrement).

Voici un exemple simple utilisant Array.CopyTo.Je pense que cela répond à votre question et donne un exemple d'utilisation de CopyTo - je suis toujours perplexe lorsque j'ai besoin d'utiliser cette fonction car l'aide est un peu floue - l'index est la position dans le tableau de destination où se produit l'insertion.

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

Je suppose que vous ne pouvez pas faire plus simple.

J'avais besoin d'une solution pour combiner un nombre inconnu de tableaux.

Surpris, personne d'autre n'a fourni de solution en utilisant SelectMany avec params.

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

Si vous ne voulez pas d'éléments distincts, supprimez simplement distinct.

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

Note:Il n'y a certainement aucune garantie de commande lors de l'utilisation de distinct.

C'est ce que j'ai trouvé.Fonctionne pour un nombre variable de tableaux.

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 }

Je suppose que vous utilisez vos propres types de tableaux, par opposition aux tableaux .NET intégrés :

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

Une autre façon de procéder consisterait à utiliser la classe ArrayList intégrée.

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

Les deux exemples sont en 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 + " ");  

En utilisant le code ci-dessus, deux tableaux peuvent être facilement fusionnés.

Méthode créée et d'extension pour gérer 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;
    }
}

Ce code fonctionnera dans tous les cas :

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

Essaye ça:

ArrayLIst al = new ArrayList();
al.AddRange(array_1);
al.AddRange(array_2);
al.AddRange(array_3);
array_4 = al.ToArray();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top