41 votes

Préfixer à un tableau C#

Étant donné un byte[] valeurs peuplé en C#, je veux ajouter la valeur (byte)0x00 au début du tableau. Je suppose que cela nécessitera de créer un nouveau tableau et d'y ajouter le contenu de l'ancien tableau. La vitesse est un aspect important de mon application. Quel est le meilleur moyen de le faire?

-- ÉDITER --

Le byte[] est utilisé pour stocker les paramètres de l'algorithme de signature numérique (DSA). L'opération ne devra être effectuée qu'une seule fois par tableau, mais la vitesse est importante car je peux potentiellement effectuer cette opération sur de nombreux byte[] différents.

3voto

Desmond Cassidy Points 51

Je sais que c'est un post TRÈS vieux mais j'aime vraiment utiliser lambda. Bien sûr, mon code n'est peut-être pas la manière la plus efficace, mais il est lisible et en une seule ligne. J'utilise une combinaison de .Concat et ArraySegment.

 string[] originalStringArray = new string[] { "1", "2", "3", "5", "6" };
 int firstElementZero = 0;
 int insertAtPositionZeroBased = 3;
 string stringToPrepend = "0";
 string stringToInsert = "FOUR"; // Délibéré !!!

 originalStringArray = new string[] { stringToPrepend }
            .Concat(originalStringArray).ToArray();

 insertAtPositionZeroBased += 1; // PARCE QUE nous avons préfixé !!
 originalStringArray = new ArraySegment(originalStringArray, firstElementZero, insertAtPositionZeroBased)       
                .Concat(new string[] { stringToInsert })
                .Concat(new ArraySegment(originalStringArray, insertAtPositionZeroBased, originalStringArray.Length - insertAtPositionZeroBased)).ToArray();

2voto

Sean U Points 4476

Le meilleur choix dépend de ce que vous allez faire avec cette collection plus tard. Si c'est la seule modification de longueur qui sera jamais faite, votre meilleur pari est de créer un nouveau tableau avec un emplacement supplémentaire et d'utiliser Array.Copy() pour le reste. Pas besoin d'initialiser la première valeur, car les nouveaux tableaux C# sont toujours mis à zéro :

byte[] PrependWithZero(byte[] input)
{
    var newArray = new byte[input.Length + 1];
    Array.Copy(input, 0, newArray, 1, input.Length);
    return newArray;
}

S'il y a d'autres modifications de longueur qui pourraient se produire, l'option la plus performante pourrait être d'utiliser une List dès le départ, tant que les ajouts ne se font pas toujours au début. (Dans ce cas, même une liste chaînée pourrait ne pas être une option que vous pouvez ignorer trop rapidement.) :

var list = new List(input);
list.Insert(0, 0);

1voto

Dan Points 1

Vous pouvez laisser le compilateur prendre les commandes avec les optimisations en utilisant les nouvelles expressions de collection et élément de diffusion :

byte[] newArray = [0x00, ..oldArray];

En jetant un œil à mon IL sur la version Release, il semble qu'il crée un nouveau tableau avec la longueur de oldArray + 1, et en ajoutant la boucle for l'autre tableau.
Ce n'est donc pas aussi efficace que Array.Copy, cependant, c'est une belle ligne unique qui pourrait être améliorée avec le temps et par le compilateur en fonction de votre configuration.

Apparemment, l'élément de diffusion prend le GetEnumerator sur un CopyTo applicable. Peut-être que je rate quelque chose!

À partir de la documentation (où le type cible est un tableau) :

Si l'élément est un élément de diffusion alors l'un des éléments suivants est utilisé :

  • Un membre d'une interface ou d'un type bien connu est invoqué pour copier les éléments de l'expression de l'élément de diffusion à l'instance d'initialisation.
  • Un exemplaire d'un GetEnumerator applicable ou d'une méthode d'extension est invoqué sur l'expression d'élément de diffusion et pour chaque élément de l'énumérateur, l'indexeur de l'instance d'initialisation est invoqué pour ajouter l'élément au index actuel. Si l'énumérateur implémente IDisposable, alors Dispose sera appelé après énumération, peu importe les exceptions.
  • Un exemplaire d'un CopyTo applicable ou d'une méthode d'extension est invoqué sur l'expression de l'élément de diffusion avec l'instance d'initialisation et int index en tant qu'arguments.

0voto

Margus Points 6175

Je suis conscient(e) que ce message a été accepté il y a plus de 4 ans, mais pour ceux à qui cela pourrait être pertinent, Buffer.BlockCopy serait plus rapide.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X