Есть ли способ в Javascript легко написать что-то вроде этого:
[1,2,3].times do {
something();
}
Может быть, любая библиотека, которая может поддерживать подобный синтаксис?
Обновление: чтобы уточнить - я хотел бы, something()
чтобы меня вызывали 1,2 и 3 раза соответственно для каждой итерации элемента массива
javascript
jquery
underscore.js
BreakPhreak
источник
источник
Ответы:
Этот ответ основан на
Array.forEach
нативной ванили , без какой-либо библиотеки .Чтобы позвонить
something()
3 раза, используйте:[1,2,3].forEach(function(i) { something(); });
учитывая следующую функцию:
function something(){ console.log('something') }
Выход будет
Чтобы ответить на эти вопросы, вот способ сделать звонок
something()
1, 2 и 3 раза соответственно:Это 2017 год, вы можете использовать ES6:
[1,2,3].forEach(i => Array(i).fill(i).forEach(_ => { something() }))
или в старом добром ES5:
[1,2,3].forEach(function(i) { Array(i).fill(i).forEach(function() { something() }) }))
В обоих случаях выход будет
Выход будет
(один раз, затем дважды, затем 3 раза)
источник
something
вызывается только 3 раза, его следует вызывать 6 раз.[...Array(i)]
илиArray(i).fill()
, в зависимости от ваших потребностей для фактических индексов..forEach(something)
Просто используйте цикл:
var times = 10; for(var i=0; i < times; i++){ doSomething(); }
источник
Возможная альтернатива ES6.
Array.from(Array(3)).forEach((x, i) => { something(); });
Причем, если хотите, «вызывается 1,2 и 3 раза соответственно».
Array.from(Array(3)).forEach((x, i) => { Array.from(Array(i+1)).forEach((x, i2) => { console.log(`Something ${ i } ${ i2 }`) }); });
Обновить:
Взято из fill-array-with-undefined
Это кажется более оптимизированным способом создания начального массива, я также обновил его, чтобы использовать вторую функцию сопоставления параметров, предложенную @ felix-eve.
Array.from({ length: 3 }, (x, i) => { something(); });
источник
Array.from(Array(3)).forEach(something)
Array.from()
имеет необязательный второй параметрmapFn
, который позволяет вам выполнять функцию карты для каждого элемента массива, поэтому нет необходимости использовать forEach. Вы можете просто сделать:Array.from({length: 3}, () => somthing() )
Поскольку вы упоминаете Underscore:
Предполагается,
f
что это функция, которую вы хотите вызвать:_.each([1,2,3], function (n) { _.times(n, f) });
сделает свое дело. Например, с
f = function (x) { console.log(x); }
, вы попадете на консоль:0 0 1 0 1 2
источник
_(3).times(function(n){return n;});
должен сделать свое дело. Смотрите документацию здесь.С lodash :
_.each([1, 2, 3], (item) => { doSomeThing(item); }); //Or: _.each([1, 2, 3], doSomeThing);
Или, если вы хотите сделать что-то N раз :
const N = 10; _.times(N, () => { doSomeThing(); }); //Or shorter: _.times(N, doSomeThing);
Обратитесь к этой ссылке для
lodash
установкиисточник
Создайте массив и
fill
все элементы сundefined
такимmap
методом могут работать:// run 5 times: Array(5).fill().map((item, i)=>{ console.log(i) // print index })
Если вы хотите сделать вышеупомянутое более «отрицательным», мое текущее решение, основанное на мнении, будет:
Показать фрагмент кода
const iterate = times => callback => Array(times).fill().map((n,i) => callback(i)) iterate(3)(console.log)
Используя старый (обратный) цикл:
// run 5 times: for( let i=5; i--; ) console.log(i)
Или как декларативное «пока» :
Показать фрагмент кода
const times = count => callback => { while(count--) callback(count) } times(3)(console.log)
источник
Вы также можете сделать то же самое с деструктуризацией следующим образом
[...Array(3)].forEach( _ => console.log('do something'));
или если вам нужен индекс
[...Array(3)].forEach(( _, index) => console.log('do something'));
источник
Если вы не можете использовать Underscorejs, вы можете реализовать его самостоятельно. Прикрепив новые методы к прототипам Number и String, вы можете сделать это следующим образом (используя стрелочные функции 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) );
Вам просто нужно создать выражение функции (с любым именем) и назначить его любому имени свойства (на прототипах), к которому вы хотите получить доступ, как:
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;
источник
Существует фантастическая библиотека Ramda, похожая на Underscore и Lodash, но более мощная.
const R = require('ramda'); R.call(R.times(() => { console.log('do something') }), 5);
Ramda содержит множество полезных функций. См. Документацию Ramda
источник
Вы можете использовать длину массива для выполнения вашей задачи количество раз.
var arr = [1,2,3]; for(var i=0; i < arr.length; i++){ doSomething(); }
или
var arr = [1,2,3]; do { } while (i++ < arr.length);
источник
ты можешь использовать
Array.forEach
пример:
function logArrayElements(element, index, array) { console.log("a[" + index + "] = " + element); } [2, 5, 9].forEach(logArrayElements)
или с jQuery
$.each([52, 97], function(index, value) { alert(index + ': ' + value); });
http://api.jquery.com/jQuery.each/
источник
forEach
поддерживается только в IE версии 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(); } } }
Вы можете назвать это так:
times(3,4); times(1,2,3,4); times(1,3,5,7,9);
источник
// calls doSomething 42 times Array( 42 ).join( "x" ).split( "" ).forEach( doSomething );
а также
// creates 42 somethings var somethings = Array( 42 ).join( "x" ).split( "" ).map( () => buildSomething(); );
или (через https://stackoverflow.com/a/20066663/275501 )
Array.apply(null, {length: 42}).forEach( doSomething );
источник
var times = [1,2,3]; for(var i = 0; i < times.length; i++) { for(var j = 0; j < times[i];j++) { // do something } }
Использование jQuery
.each()
$([1,2,3]).each(function(i, val) { for(var j = 0; j < val;j++) { // do something } });
ИЛИ
var x = [1,2,3]; $(x).each(function(i, val) { for(var j = 0; j < val;j++) { // do something } });
РЕДАКТИРОВАТЬ
Вы можете сделать, как показано ниже, на чистом JS:
var times = [1,2,3]; times.forEach(function(i) { // do something });
источник
Просто используйте вложенный цикл (возможно, заключенный в функцию)
function times( fct, times ) { for( var i=0; i<times.length; ++i ) { for( var j=0; j<times[i]; ++j ) { fct(); } } }
Тогда просто назовите это так:
times( doSomething, [1,2,3] );
источник
Все эти ответы хороши и хороши, и IMO @Andreas - лучший, но много раз в JS нам приходится делать что-то асинхронно, в этом случае async охватывает вас:
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 });
Эти «временные» функции не очень полезны для кода большинства приложений, но должны быть полезны для тестирования.
источник
const loop (fn, times) => { if (!times) { return } fn() loop(fn, times - 1) } loop(something, 3)
источник
Учитывая функцию
something
:function something() { console.log("did something") }
И
times
вArray
прототип добавлен новый метод :Array.prototype.times = function(f){ for(v of this) for(var _ of Array(v)) f(); }
Этот код:
[1,2,3].times(something)
Выводит это:
Что, я думаю, отвечает на ваш обновленный вопрос (5 лет спустя), но мне интересно, насколько полезно работать с массивом? Разве эффект не будет таким же, как при вызове
[6].times(something)
, который, в свою очередь, можно записать как:for(_ of Array(6)) something();
(хотя использование
_
в качестве нежелательной переменной, вероятно, приведет к сбою lodash или подчеркивания, если вы его используете)источник
let
as in,for (let _ of Array(6)) something()
чтобы предотвратить затирание lodash за пределами, по крайней мере, для.Array.from (ES6)
function doSomthing() { ... }
Используйте это так:
Array.from(Array(length).keys()).forEach(doSomthing);
Или
Array.from({ length }, (v, i) => i).forEach(doSomthing);
Или
// array start counting from 1 Array.from({ length }, (v, i) => ++i).forEach(doSomthing);
источник
Использование
Array.from
и.forEach
.let length = 5; Array.from({length}).forEach((v, i) => { console.log(`#${i}`); });
источник
Предполагая, что мы можем использовать какой-то синтаксис ES6, такой как оператор распространения, мы захотим сделать что-то столько раз, сколько сумма всех чисел в коллекции.
В этом случае, если times равно
[1,2,3]
, общее количество раз будет 6, т.е. 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
Этот пост должен быть полезен, если логика построения и распространения массива не очевидна.
источник
Реализация TypeScript:
Для тех из вас , кто заинтересован в том , как реализовать
String.times
иNumber.times
таким образом , что типобезопасен и работает сthisArg
, вот я идти: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(() => {}) }
Ссылку на TypeScript Playground с некоторыми примерами можно найти здесь
В этом посте реализованы решения, опубликованные: Andreas Bergström , vinyll , Ozay Duman и SeregPie.
источник