83 votes

Idiome pour "répéter n fois" ?

Voici une façon quelque peu inutile et peu pratique de produire un tableau de 3 nombres aléatoires en JS :

[1, 1, 1].map(Math.random) // Outputs: [0.63244645928, 0.59692098067, 0.73627558014]

L'utilisation d'un tableau fictif (par ex. [1, 1, 1] ), afin de pouvoir appeler map sur elle, est -- pour des n -- à la fois inutile (en termes de mémoire) et peu pratique.

Ce que l'on souhaiterait, c'est une sorte d'hypothèse :

repeat(3, Math.random) // Outputs: [0.214259553965, 0.002260502324, 0.452618881464]

Qu'est-ce qui se rapproche le plus de ce que l'on peut faire en utilisant du JavaScript classique ?

Je connais des bibliothèques comme Underscore, mais j'essaie d'éviter les bibliothèques ici.

J'ai examiné les réponses aux questions suivantes Répéter une chaîne de caractères un certain nombre de fois mais elle n'est pas applicable en général. Par exemple :

Array(3).map(Math.random) // Outputs: [undefined, undefined, undefined]
Array(4).join(Math.random()) // Outputs a concatenation of a repeated number
Array(3).fill(Math.random()) // Fills with the same number

Plusieurs autres réponses proposent de modifier une classe intégrée ; une pratique que je considère comme totalement inacceptable.

137voto

Ilpo Oksanen Points 3680

Il peut se faire en utilisant Array.prototype.map mais le tableau ne peut pas être vide. Remplir d'abord :

console.log(
    Array(3).fill().map(Math.random)
);

Explication :

En new Array(3) Le constructeur crée un tableau clairsemé (ou le réseau "holey", comme l'appelle l'équipe V8 ) comportant trois trous et d'une longueur de trois . Cela signifie qu'il est équivalent à [,,,] qui crée [<empty>, <empty>, <empty>,] (notez que JavaScript virgules de fin ). Notez qu'un emplacement vide, c'est-à-dire un trou, n'est pas la même chose que undefined en tant que valeur attribuée. undefined est une valeur réelle, alors que <empty> n'est qu'une lacune dans le tableau.

Array.prototype.map est appelé une fois pour chaque élément du tableau . Mais comme un tableau vide n'a pas de valeurs assignées, le rappel n'est pas appelé du tout. Par exemple, [1,,2].map(v=>v*2) donnerait [2,,4] ; l'emplacement du milieu est ignoré, car il y a une lacune à cet endroit.

Entrer Array.prototype.fill(value, start?, end?) avec un seul argument, il remplit chaque emplacement du tableau avec la valeur spécifiée. Techniquement, le premier paramètre n'est pas optionnel, mais en l'omettant, undefined est utilisée comme valeur. Ce n'est pas grave, car la valeur n'est de toute façon pas utilisée. De cette manière Array(3).fill() nous donne [undefined, undefined, undefined] .

Maintenant que le tableau contient des valeurs, il peut être mappé, comme indiqué ci-dessus.


Vous pouvez également spread le vide array en valeurs de undefined avant la mise en correspondance :

console.log(
    [...Array(3)].map(Math.random)
);

Explication :

Opérateurs de tableau introduits dans ECMAScript2015 ou plus récent traiter les trous dans les tableaux comme des undefined valeurs . Array.prototype.map a été introduit dans ES5 (I.E. ce qui a précédé ES2015 ), où, de manière confuse, les trous dans les tableaux doivent être ignorés, ce qui crée un peu d'incohérence dans les fonctions JS Array en fonction de l'édition d'ECMAScript dans laquelle elles ont été publiées.

L'opérateur de diffusion ... a été introduit dans ES2015 Ainsi, conformément à la spécification, il convertit tous les trous du tableau donné en valeurs de undefined . En d'autres termes, [...Array(3)] nous donne [undefined, undefined, undefined] , tout comme Array(3).fill() ci-dessus.


Il est parfois nécessaire d'introduire des nombres de manière séquentielle. Comme l'a souligné Kevin Danikowski , Array.prototype.map vous donne cette possibilité dès le départ, puisque le deuxième paramètre est la touche actuelle :

const Fibonacci = n => Math.round(((5**.5 + 1) / 2)**n / 5**.5);

console.log(
    Array(10).fill().map((_, i) => Fibonacci(++i))
);

41voto

David Brown Points 7090

Underscore.js a une fonction fois qui fait exactement ce que vous voulez :

_.times(3, Math.random)

Si vous ne voulez pas utiliser Underscore, vous pouvez simplement écrire votre propre times (copiée et légèrement simplifiée à partir de la source Underscore) :

times = function(n, iterator) {
  var accum = Array(Math.max(0, n));
  for (var i = 0; i < n; i++) accum[i] = iterator.call();
  return accum;
};

25voto

Anona112 Points 38

Le plus court et le plus élégant ES6 :

let times = (n, f) => { while(n-- > 0) f(); }

oh, ce n'est pas pour créer un tableau, mais c'est quand même sympa !

times(3, () => print('wow'))

ou Ruby :

Object.assign(Number.prototype, { times(f) { x = this; while(x-- > 0) f(); }})
3..times(() => print('wow'))

24voto

trincot Points 10112

Peut-être que le Array.from peut être utile :

var result = Array.from(Array(3), Math.random);

console.log(result);

Il y a ici un léger avantage par rapport à l'utilisation de map : map a déjà besoin d'un tableau avec toutes les entrées (peut-être créée avec fill ou la syntaxe d'étalement), pour ensuite créer le tableau final à partir de celui-ci. Au total, un map créera n entrées deux fois . Array.from n'a pas besoin d'un tableau avec des entrées, mais simplement d'un objet avec une fonction length fera l'affaire, et la propriété Array(3) fournit cela.

En fonction de vos préférences, vous pouvez donc également procéder de la manière suivante :

var result = Array.from({length:3}, Math.random);

console.log(result);

Enfin, si vous souhaitez créer un repeat pour cela, vous pouvez nommer l'argument length et utiliser la notation courte ES6 pour les littéraux d'objets :

const repeat = (length, cb) => Array.from({length}, cb);

const result = repeat(3, Math.random);
console.log(result);

6voto

vinyll Points 3643

Une façon moderne de créer ce genre de choses repeat fonction :

repeat = (n, cb) => {[...Array(n)].forEach(cb)}

Vous pouvez ensuite l'utiliser avec :

repeat(3, _ => console.log(Math.random()))

La sortie se ferait :

0.6324464592887568
0.5969209806782131
0.7362755801487572

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