279 votes

Comment remplir/instancier un tableau C# avec une seule valeur ?

Je sais que les tableaux instanciés de types de valeurs en C# sont automatiquement remplis avec la valeur valeur par défaut du type (par exemple, false pour bool, 0 pour int, etc.).

Existe-t-il un moyen de remplir automatiquement un tableau avec une valeur d'amorçage qui n'est pas la valeur par défaut ? Soit à la création, soit par une méthode intégrée par la suite (comme la méthode Java Arrays.fill() ) ? Imaginons que je veuille un tableau booléen qui soit vrai par défaut, au lieu de faux. Existe-t-il un moyen intégré de faire cela, ou faut-il simplement itérer dans le tableau avec une boucle for ?

 // Example pseudo-code:
 bool[] abValues = new[1000000];
 Array.Populate(abValues, true);

 // Currently how I'm handling this:
 bool[] abValues = new[1000000];
 for (int i = 0; i < 1000000; i++)
 {
     abValues[i] = true;
 }

Devoir itérer dans le tableau et "réinitialiser" chaque valeur à true semble inefficace. Existe-t-il un moyen de contourner ce problème ? Peut-être en inversant toutes les valeurs ?

Après avoir tapé cette question et y avoir réfléchi, je suppose que les valeurs par défaut sont simplement le résultat de la façon dont C# gère l'allocation de la mémoire de ces objets en coulisse, donc j'imagine qu'il n'est probablement pas possible de le faire. Mais j'aimerais quand même en avoir le cœur net !

0 votes

Je change généralement le nom de is_found en is_still_hiding. J'ai aimé les réponses, j'avais besoin de faire la même chose pour un tableau d'int dans un cas de test. (bonne question)

266voto

Rony Points 6340
Enumerable.Repeat(true, 1000000).ToArray();

96 votes

Bien que cela fonctionne, ce n'est pas vraiment une bonne solution car elle est très lente ; en fait, elle est environ 4 fois plus lente que l'itération avec une boucle for.

5 votes

Oui c'est vrai, quand on considère les performances la boucle for est plus rapide

7 votes

Pour voir des exemples concrets, consultez le site C# Initialiser un tableau .

170voto

JaredPar Points 333733

Je ne connais pas de méthode d'encadrement, mais vous pourriez écrire une aide rapide qui le ferait pour vous.

public static void Populate<T>(this T[] arr, T value ) {
  for ( int i = 0; i < arr.Length;i++ ) {
    arr[i] = value;
  }
}

1 votes

C'est une très bonne idée, Jared. Je pense vraiment que je pourrais ajouter quelque chose comme ça à ma bibliothèque d'extension si aucune autre réponse ne surgit !

6 votes

Préférez ++i au lieu de i++ si vous n'avez pas besoin de la copie.

0 votes

Robert Dailey - pouvez-vous expliquer ?

96voto

bytebender Points 5064

Créer un nouveau tableau avec un millier true valeurs :

var items = Enumerable.Repeat<bool>(true, 1000).ToArray();  // Or ToList(), etc.

De même, vous pouvez générer des séquences d'entiers :

var items = Enumerable.Range(0, 1000).ToArray();  // 0..999

16 votes

Pas mal, mais c'est toujours plus lent qu'une boucle for par un facteur de 4.

1 votes

Patjbs en théorie, dans le futur, Enumerable.Repeat sera plus rapide car il utilisera une implémentation parallèle.

2 votes

@PetarPetrov Cela n'arrivera jamais à cause du thrashing du cache. Je suis pratiquement certain qu'en raison de la nature du cache du processeur, l'exécution d'un travail en parallèle sur un seul tableau sera toujours plus lente, quoi qu'il arrive, car l'ordinateur s'attend à un travail synchrone et charge les données en conséquence.

26voto

LBushkin Points 60611

Pour les grands tableaux ou les tableaux qui seront de taille variable, vous devriez probablement utiliser :

Enumerable.Repeat(true, 1000000).ToArray();

Pour les petits tableaux, vous pouvez utiliser la syntaxe d'initialisation des collections en C# 3 :

bool[] vals = new bool[]{ false, false, false, false, false, false, false };

L'avantage de la syntaxe d'initialisation des collections est que vous n'êtes pas obligé d'utiliser la même valeur dans chaque slot et que vous pouvez utiliser des expressions ou des fonctions pour initialiser un slot. En outre, je pense que vous évitez le coût de l'initialisation du slot du tableau à la valeur par défaut. Donc, par exemple :

bool[] vals = new bool[]{ false, true, false, !(a ||b) && c, SomeBoolMethod() };

0 votes

Et pour initialiser un tableau float[] : float[] AlzCalDefault = new float[] {(float) 0.5, 18, 500, 1, 0};

0 votes

Pour information, l'initialisation d'un tableau peut être effectuée dans n'importe quelle version de C# : bool[] vals = { false, true, false, !(a || b) && c, SomeBoolMethod() };

1 votes

"éviter le coût de l'initialisation de l'emplacement du tableau à la valeur par défaut" est une bonne idée, mais ni vous ni le compilateur n'ont le moindre contrôle sur ce point - l'allocateur .NET distribue des blocs de mémoire déjà mis à zéro.

25voto

MrFox Points 1492

Si votre tableau est si grand, vous devriez utiliser BitArray. Il utilise un bit pour chaque bool au lieu d'un octet (comme dans un tableau de bools) et vous pouvez aussi mettre tous les bits à true avec les opérateurs de bit. Ou simplement initialiser sur true. Si vous n'avez besoin de le faire qu'une seule fois, cela ne vous coûtera que plus cher.

System.Collections.BitArray falses = new System.Collections.BitArray(100000, false);
System.Collections.BitArray trues = new System.Collections.BitArray(100000, true);

// Now both contain only true values.
falses.And(trues);

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