¿Hay alguna forma en Javascript de escribir algo como esto fácilmente?
[1,2,3].times do {
something();
}
¿Alguna biblioteca que pueda soportar alguna sintaxis similar tal vez?
Actualización: para aclarar, me gustaría que me something()
llamen 1, 2 y 3 veces respectivamente para cada iteración del elemento de la matriz
javascript
jquery
underscore.js
BreakPhreak
fuente
fuente
Respuestas:
Esta respuesta se basa
Array.forEach
, sin ninguna biblioteca, solo vainilla nativa .Básicamente, para llamar
something()
3 veces, use:[1,2,3].forEach(function(i) { something(); });
considerando la siguiente función:
function something(){ console.log('something') }
La salida será
Para completar estas preguntas, aquí tienes una forma de llamar
something()
1, 2 y 3 veces respectivamente:Es 2017, puede usar ES6:
[1,2,3].forEach(i => Array(i).fill(i).forEach(_ => { something() }))
o en el viejo ES5:
[1,2,3].forEach(function(i) { Array(i).fill(i).forEach(function() { something() }) }))
En ambos casos, la salida será
La salida será
(una vez, luego dos, luego 3 veces)
fuente
something
solo se llama 3 veces, debe llamarse 6 veces.[...Array(i)]
oArray(i).fill()
, según sus necesidades para los índices reales..forEach(something)
Solo usa un bucle:
var times = 10; for(var i=0; i < times; i++){ doSomething(); }
fuente
Posible alternativa a ES6.
Array.from(Array(3)).forEach((x, i) => { something(); });
Y, si quieres que "se llame 1,2 y 3 veces respectivamente".
Array.from(Array(3)).forEach((x, i) => { Array.from(Array(i+1)).forEach((x, i2) => { console.log(`Something ${ i } ${ i2 }`) }); });
Actualizar:
Tomado de fill-arrays-with-undefined
Esta parece ser una forma más optimizada de crear la matriz inicial, también la he actualizado para usar la función de mapa de segundo parámetro sugerida por @ felix-eve.
Array.from({ length: 3 }, (x, i) => { something(); });
fuente
Array.from(Array(3)).forEach(something)
Array.from()
tiene un segundo parámetro opcionalmapFn
, que le permite ejecutar una función de mapa en cada elemento de la matriz, por lo que no es necesario usar forEach. Simplemente puede hacer:Array.from({length: 3}, () => somthing() )
Como mencionas el subrayado:
Suponiendo que
f
es la función que desea llamar:_.each([1,2,3], function (n) { _.times(n, f) });
hará el truco. Por ejemplo, con
f = function (x) { console.log(x); }
, obtendrá en su consola:0 0 1 0 1 2
fuente
_(3).times(function(n){return n;});
debería hacer el truco. Vea los documentos aquí.Con lodash :
_.each([1, 2, 3], (item) => { doSomeThing(item); }); //Or: _.each([1, 2, 3], doSomeThing);
O si quieres hacer algo N veces :
const N = 10; _.times(N, () => { doSomeThing(); }); //Or shorter: _.times(N, doSomeThing);
Consulte este enlace para la
lodash
instalación.fuente
Crear una matriz y
fill
todos los artículos conundefined
lo quemap
el método podría funcionar:// run 5 times: Array(5).fill().map((item, i)=>{ console.log(i) // print index })
Si desea que lo anterior sea más "declerativo", mi solución basada en opiniones actualmente sería:
Mostrar fragmento de código
const iterate = times => callback => Array(times).fill().map((n,i) => callback(i)) iterate(3)(console.log)
Usando el bucle de la vieja escuela (inverso):
// run 5 times: for( let i=5; i--; ) console.log(i)
O como un "mientras" declarativo :
Mostrar fragmento de código
const times = count => callback => { while(count--) callback(count) } times(3)(console.log)
fuente
También puede hacer lo mismo con la desestructuración de la siguiente manera
[...Array(3)].forEach( _ => console.log('do something'));
o si necesitas index
[...Array(3)].forEach(( _, index) => console.log('do something'));
fuente
Si no puede usar Underscorejs, puede implementarlo usted mismo. Al adjuntar nuevos métodos a los prototipos de números y cadenas, puede hacerlo así (usando las funciones de flecha de 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) );
Simplemente tiene que crear una expresión de función (de cualquier nombre) y asignarla a cualquier nombre de propiedad (en los prototipos) al que le gustaría acceder como:
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;
fuente
Hay una biblioteca fantástica llamada Ramda, que es similar a Underscore y Lodash, pero es más poderosa.
const R = require('ramda'); R.call(R.times(() => { console.log('do something') }), 5);
Ramda contiene muchas funciones útiles. Ver la documentación de Ramda
fuente
Puede usar la longitud de la matriz para ejecutar varias veces su tarea.
var arr = [1,2,3]; for(var i=0; i < arr.length; i++){ doSomething(); }
o
var arr = [1,2,3]; do { } while (i++ < arr.length);
fuente
puedes usar
Array.forEach
ejemplo:
function logArrayElements(element, index, array) { console.log("a[" + index + "] = " + element); } [2, 5, 9].forEach(logArrayElements)
o con jQuery
$.each([52, 97], function(index, value) { alert(index + ': ' + value); });
http://api.jquery.com/jQuery.each/
fuente
forEach
solo se admite en IE desde la versión 9: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…times = function () { var length = arguments.length; for (var i = 0; i < length ; i++) { for (var j = 0; j < arguments[i]; j++) { dosomthing(); } } }
Puedes llamarlo así:
times(3,4); times(1,2,3,4); times(1,3,5,7,9);
fuente
// calls doSomething 42 times Array( 42 ).join( "x" ).split( "" ).forEach( doSomething );
y
// creates 42 somethings var somethings = Array( 42 ).join( "x" ).split( "" ).map( () => buildSomething(); );
o (a través de https://stackoverflow.com/a/20066663/275501 )
Array.apply(null, {length: 42}).forEach( doSomething );
fuente
var times = [1,2,3]; for(var i = 0; i < times.length; i++) { for(var j = 0; j < times[i];j++) { // do something } }
Usando jQuery
.each()
$([1,2,3]).each(function(i, val) { for(var j = 0; j < val;j++) { // do something } });
O
var x = [1,2,3]; $(x).each(function(i, val) { for(var j = 0; j < val;j++) { // do something } });
EDITAR
Puede hacer lo siguiente con JS puro:
var times = [1,2,3]; times.forEach(function(i) { // do something });
fuente
Solo use un bucle anidado (tal vez incluido en una función)
function times( fct, times ) { for( var i=0; i<times.length; ++i ) { for( var j=0; j<times[i]; ++j ) { fct(); } } }
Entonces llámalo así:
times( doSomething, [1,2,3] );
fuente
Estas respuestas son todas buenas y están bien y, en mi opinión, @Andreas es la mejor, pero muchas veces en JS tenemos que hacer las cosas de forma asincrónica, en ese caso, async lo tiene cubierto:
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 });
Estas características de 'tiempos' no son muy útiles para la mayoría de los códigos de aplicaciones, pero deberían ser útiles para las pruebas.
fuente
const loop (fn, times) => { if (!times) { return } fn() loop(fn, times - 1) } loop(something, 3)
fuente
Dada una función
something
:function something() { console.log("did something") }
Y un nuevo método
times
agregado alArray
prototipo:Array.prototype.times = function(f){ for(v of this) for(var _ of Array(v)) f(); }
Este código:
[1,2,3].times(something)
Produce esto:
Lo que creo que responde a su pregunta actualizada (5 años después), pero me pregunto qué tan útil es que esto funcione en un arreglo ¿No sería el efecto el mismo que llamar
[6].times(something)
, que a su vez podría escribirse como:for(_ of Array(6)) something();
(aunque el uso de
_
como una variable basura probablemente golpeará lodash o subrayará si lo está usando)fuente
let
as infor (let _ of Array(6)) something()
para evitar que lodash golpee fuera de la por al menos.Matriz. De (ES6)
function doSomthing() { ... }
Úselo así:
Array.from(Array(length).keys()).forEach(doSomthing);
O
Array.from({ length }, (v, i) => i).forEach(doSomthing);
O
// array start counting from 1 Array.from({ length }, (v, i) => ++i).forEach(doSomthing);
fuente
Usando
Array.from
y.forEach
.let length = 5; Array.from({length}).forEach((v, i) => { console.log(`#${i}`); });
fuente
Suponiendo que podemos usar alguna sintaxis de ES6 como el operador de propagación, querremos hacer algo tantas veces como la suma de todos los números de la colección.
En este caso, si tiempos es igual a
[1,2,3]
, el número total de veces será 6, es decir, 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
Esta publicación debería ser útil si la lógica detrás de la construcción y distribución de una matriz no es evidente.
fuente
Implementación de TypeScript:
Para aquellos de ustedes que estén interesados en cómo implementar
String.times
yNumber.times
de una manera segura de escribir y que funcione con elthisArg
, aquí tiene:declare global { interface Number { times: (callbackFn: (iteration: number) => void, thisArg?: any) => void; } interface String { times: (callbackFn: (iteration: number) => void, thisArg?: any) => void; } } Number.prototype.times = function (callbackFn, thisArg) { const num = this.valueOf() if (typeof callbackFn !== "function" ) { throw new TypeError("callbackFn is not a function") } if (num < 0) { throw new RangeError('Must not be negative') } if (!isFinite(num)) { throw new RangeError('Must be Finite') } if (isNaN(num)) { throw new RangeError('Must not be NaN') } [...Array(num)].forEach((_, i) => callbackFn.bind(thisArg, i + 1)()) // Other elegant solutions // new Array<null>(num).fill(null).forEach(() => {}) // Array.from({length: num}).forEach(() => {}) } String.prototype.times = function (callbackFn, thisArg) { let num = parseInt(this.valueOf()) if (typeof callbackFn !== "function" ) { throw new TypeError("callbackFn is not a function") } if (num < 0) { throw new RangeError('Must not be negative') } if (!isFinite(num)) { throw new RangeError('Must be Finite') } // num is NaN if `this` is an empty string if (isNaN(num)) { num = 0 } [...Array(num)].forEach((_, i) => callbackFn.bind(thisArg, i + 1)()) // Other elegant solutions // new Array<null>(num).fill(null).forEach(() => {}) // Array.from({length: num}).forEach(() => {}) }
Aquí se puede encontrar un enlace a TypeScript Playground con algunos ejemplos.
Esta publicación implementa soluciones publicadas por: Andreas Bergström , vinyll , Ozay Duman y SeregPie
fuente