web-dev-qa-db-fra.com

faire <quelque chose> N fois (syntaxe déclarative)

Existe-t-il un moyen en Javascript d’écrire facilement quelque chose comme ceci:

[1,2,3].times do {
  something();
}

Toute bibliothèque qui pourrait supporter une syntaxe similaire peut-être?

Mise à jour: à préciser - J'aimerais que something() soit appelé 1,2 et 3 fois respectivement pour chaque itération d'élément de tableau

53
BreakPhreak

Cette réponse est basée sur Array.forEach, sans aucune bibliothèque, juste native Vanilla .

Pour appeler fondamentalement something() 3 fois, utilisez:

[1,2,3].forEach(function(i) {
  something();
});

compte tenu de la fonction suivante:

function something(){ console.log('something') }

La sortie sera 

something
something
something

Pour compléter ces questions, voici une façon de téléphoner à something() 1, 2 et 3 fois respectivement:

Nous sommes en 2017, vous pouvez utiliser ES6:

[1,2,3].forEach(i => Array(i).fill(i).forEach(_ => {
  something()
}))

ou en bon vieux ES5:

[1,2,3].forEach(function(i) {
  Array(i).fill(i).forEach(function() {
    something()
  })
}))

Dans les deux cas, la sortie sera

La sortie sera 

something

something
something

something
something
something

(une fois, puis deux fois, puis trois fois)

27
vinyll

Il suffit d'utiliser une boucle:

var times = 10;
for(var i=0; i < times; i++){
    doSomething();
}
58
ahren

Alternative ES6 possible.

Array.from(Array(3)).forEach((x, i) => {
  something();
});

Et, si vous voulez "être appelé respectivement 1,2 et 3 fois".

Array.from(Array(3)).forEach((x, i) => {
  Array.from(Array(i+1)).forEach((x, i2) => {
    console.log(`Something ${ i } ${ i2 }`)
  });
});

Mettre à jour:

Tiré de filling-array-with-undefined

Cela semble être un moyen plus optimisé de créer le tableau initial. 

Array.from({ length: 3 }).forEach((x, i) => {
  something();
});
27
nverba

Puisque vous mentionnez Underscore:

En supposant que f est la fonction que vous souhaitez appeler:

_.each([1,2,3], function (n) { _.times(n, f) });

fera l'affaire. Par exemple, avec f = function (x) { console.log(x); }, vous obtiendrez sur votre console: 0 0 1 0 1 2

19
ggozad

Nous pouvons utiliser lodash pour effectuer ce travail en:

_.each([1, 2, 3], function(item) {
   doSomeThing(item);
});

//Or:
_.each([1, 2, 3], doSomeThing);

Ou si vous voulez faire quelque chose N fois:

var n = 10;
_.times(n, function() {
   doSomeThing();
});

//Or: 
_.times(n, doSomeThing);

Référence ce lien pour l'installation de lodash

12
Tho

Si vous ne pouvez pas utiliser Underscorejs, vous pouvez le mettre en œuvre vous-même. En associant de nouvelles méthodes aux prototypes Number et String, vous pouvez le faire comme ceci (en utilisant les fonctions de flèche ES6):

// With String
"5".times( (i) => console.log("number "+i) );

// With number variable
var five = 5;
five.times( (i) => console.log("number "+i) );

// With number literal (parentheses required)
(5).times( (i) => console.log("number "+i) );

Vous devez simplement créer une expression de fonction (quel que soit le nom) et l'affecter au nom de la propriété (sur les prototypes) auquel vous souhaitez accéder, comme suit:

var timesFunction = function(callback) {
  if (typeof callback !== "function" ) {
    throw new TypeError("Callback is not a function");
  } else if( isNaN(parseInt(Number(this.valueOf()))) ) {
    throw new TypeError("Object is not a valid number");
  }
  for (var i = 0; i < Number(this.valueOf()); i++) {
    callback(i);
  }
};

String.prototype.times = timesFunction;
Number.prototype.times = timesFunction;
9
Andreas Bergström

Créez un tableau et fill tous les éléments avec undefined afin que map méthode puisse fonctionner:

Array.fill n'a pas de support IE

Array(5).fill().map(()=>{ 
   // Do this 5 times:
   console.log(111) 
})


Utilisation de la vénérable boucle de la vieille école:

for( let i=5; i--; ){
   // Do this 5 times:
   console.log(222) 
}

4
vsync
times = function () {
    var length = arguments.length;
    for (var i = 0; i < length ; i++) {
        for (var j = 0; j < arguments[i]; j++) {
            dosomthing();
        }
    }
}

Vous pouvez l'appeler comme ça:

times(3,4);
times(1,2,3,4);
times(1,3,5,7,9);
1
XU3352

vous pouvez utiliser

Tableau.pour chaque

exemple:

function logArrayElements(element, index, array) {  
    console.log("a[" + index + "] = " + element);  
}  
[2, 5, 9].forEach(logArrayElements)

ou avec jQuery

$.each([52, 97], function(index, value) { 
  alert(index + ': ' + value); 
});

http://api.jquery.com/jQuery.each/

1
Machu

Il existe une bibliothèque fantastique appelée Ramda, similaire à Underscore et Lodash, mais plus puissante. 

const R = require('ramda');

R.call(R.times(() => {
    console.log('do something')
}), 5);

Ramda contient de nombreuses fonctions utiles. Voir Documentation Ramda

1
Jan Bodnar
// calls doSomething 42 times
Array( 42 ).join( "x" ).split( "" ).forEach( doSomething );

et 

// creates 42 somethings
var somethings = Array( 42 ).join( "x" ).split( "" ).map( () => buildSomething(); );

ou (via https://stackoverflow.com/a/20066663/275501 )

Array.apply(null, {length: 42}).forEach( doSomething );
1
goofballLogic
var times = [1,2,3];

for(var i = 0; i < times.length;  i++) {
  for(var j = 0; j < times[i];j++) {
     // do something
  }
}

Utilisation de jQuery .each()

$([1,2,3]).each(function(i, val) {
  for(var j = 0; j < val;j++) {
     // do something
  }
});

OR

var x = [1,2,3];

$(x).each(function(i, val) {
  for(var j = 0; j < val;j++) {
     // do something
  }
});

MODIFIER

Vous pouvez faire comme ci-dessous avec du JS pur:

var times = [1,2,3];
times.forEach(function(i) {
   // do something
});
1
thecodeparadox

Vous pouvez utiliser length of array pour exécuter plusieurs fois votre tâche.

var arr = [1,2,3];

for(var i=0; i < arr.length; i++){
    doSomething();
}

ou

 var arr = [1,2,3];

 do
 {


 }
 while (i++ < arr.length);
1
Adil

Utilisez simplement une boucle imbriquée (peut-être incluse dans une fonction)

function times( fct, times ) {
  for( var i=0; i<times.length; ++i ) {
    for( var j=0; j<times[i]; ++j ) {
      fct();
    }
  }
}

Puis appelez ça comme ça:

times( doSomething, [1,2,3] );
0
Sirko

En supposant que nous puissions utiliser une syntaxe ES6 telle que l'opérateur spread, nous voudrons faire quelque chose autant de fois que la somme de tous les nombres de la collection.

Dans ce cas, si times est égal à [1,2,3], le nombre total de fois sera de 6, à savoir 1 + 2 + 3.

/**
 * @param {number[]} times
 * @param {cb} function
 */
function doTimes(times, cb) {
  // Get the sum of all the times
  const totalTimes = times.reduce((acc, time) => acc + time);
  // Call the callback as many times as the sum
  [...Array(totalTimes)].map(cb);
}

doTimes([1,2,3], () => console.log('something'));
// => Prints 'something' 6 times

Cet article devrait être utile si la logique derrière la construction et la propagation d’un tableau n’est pas évidente.

0
IliasT

Ces réponses sont toutes bonnes et bonnes et IMO @Andreas est la meilleure, mais souvent dans JS, nous devons faire les choses de manière asynchrone.

http://caolan.github.io/async/docs.html#times

const async = require('async');

async.times(5, function(n, next) {
    createUser(n, function(err, user) {
        next(err, user);
    });
}, function(err, users) {
    // we should now have 5 users
});

Ces fonctionnalités "times" ne sont pas très utiles pour la plupart des applications, mais devraient être utiles pour les tests.

0
Alexander Mills

Array.from (ES6)

function doSomthing() {
    ...
}

Utilisez-le comme suit:

Array.from(Array(length).keys()).forEach(doSomthing);

Ou

Array.from({ length }, (v, i) => i).forEach(doSomthing);

Ou

// array start counting from 1
Array.from({ length }, (v, i) => ++i).forEach(doSomthing);
0
Lior Elrom
const loop (fn, times) => {
  if (!times) { return }
  fn()
  loop(fn, times - 1)
}

loop(something, 3)
0
Goro

Utiliser Array.from et .forEach.

let length = 5;
Array.from({length}).forEach((v, i) => {
  console.log(`#${i}`);
});

0
SeregPie