do N times (declarative syntax)

Is there a way in Javascript to write something like this easily:

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

Any library that might support some similar syntax maybe?

Update: to clarify - I would like something() to be called 1,2 and 3 times respectively for each array element iteration

1

23 Answers

Just use a for loop:

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

Possible ES6 alternative.

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

And, if you want it "to be called 1,2 and 3 times respectively".

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

Update:

Taken from filling-arrays-with-undefined

This seems to be a more optimised way of creating the initial array, I've also updated this to use the second parameter map function suggested by @felix-eve.

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

This answer is based on Array.forEach, without any library, just native vanilla.

To basically call something() 3 times, use:

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

considering the following function:

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

The output will be:

something
something
something

To complete this questions, here's a way to do call something() 1, 2 and 3 times respectively:

It's 2017, you may use ES6:

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

or in good old ES5:

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

In both cases, the output will be

The output will be:

something
something
something
something
something
something

(once, then twice, then 3 times)

4

Create an Array and fill all items with undefined before using map:

👉 Read detailed reason why map is skipping never-defined array items

⚠️ Array.fill has no IE support

Array(5).fill().map((item, i) => console.log(item, i))

Or fill do the same as above without fill, by destructuring the Array, which automatically sets undefined for each item, if the item's value was not set:

[...Array(5)].map((item, i) => console.log(item, i))

If you want to make the above more "declarative", my currently opinion-based solution would be:

const iterate = times => callback => [...Array(times)].map((n,i) => callback(i))
iterate(3)(console.log)

Using old-school (reverse) loop:

// run 5 times:
for( let i=5; i--; ) console.log(i) 

Or as a declarative "while":

const run = (cb, ...args) => count => { while(count--) cb(...args) }
// executes the callback with whatever arguments, 3 times
run(console.log, 1,2,3)(3)
4

With lodash:

_.each([1, 2, 3], (item) => { doSomeThing(item);
});
//Or:
_.each([1, 2, 3], doSomeThing);

Or if you want to do something N times:

const N = 10;
_.times(N, () => { doSomeThing();
});
//Or shorter:
_.times(N, doSomeThing);

Since you mention Underscore:

Assuming f is the function you want to call:

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

will do the trick. For example, with f = function (x) { console.log(x); }, you will get on your console:0 0 1 0 1 2

3

You can also do the same thing with destructuring as follows

[...Array(3)].forEach( _ => console.log('do something'));

or if you need index

[...Array(3)].forEach(( _, index) => console.log('do something'));

If you can't use Underscorejs, you can implement it yourself. By attaching new methods to the Number and String prototypes, you could do it like this (using ES6 arrow functions):

// 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) );

You simply have to create a function expression (of whatever name) and assign it to whatever property name (on the prototypes) you would like to access it as:

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;
1

How about a simple while.

let times = 5;
while (times--) { console.log(times+1)
}

References on how this works: Falsy and Decrement (--)


Edit: If there's a possibility for times to be manipulated elsewhere, it's safer to use times-- > 0 instead of times-- to prevent an infinite loop if the times drops below 0

Just use a nested loop (maybe enclosed in a function)

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

Then just call it like this:

times( doSomething, [1,2,3] );
times = function () { var length = arguments.length; for (var i = 0; i < length ; i++) { for (var j = 0; j < arguments[i]; j++) { dosomthing(); } }
}

You can call it like this:

times(3,4);
times(1,2,3,4);
times(1,3,5,7,9);
1
const loop (fn, times) => { if (!times) { return } fn() loop(fn, times - 1)
}
loop(something, 3)

Array.from (ES6)

function doSomthing() { ...
}

Use it like so:

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

Or

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

Or

// array start counting from 1
Array.from({ length }, (v, i) => ++i).forEach(doSomthing);

There is a fantastic library called Ramda, which is similar to Underscore and Lodash, but is more powerful.

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

Ramda contains plenty of useful functions. See Ramda documentation

1

you can use

Array.forEach

example:

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

or with jQuery

$.each([52, 97], function(index, value) { alert(index + ': ' + value);
});
1
// calls doSomething 42 times
Array( 42 ).join( "x" ).split( "" ).forEach( doSomething );

and

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

or ( via )

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 }
}

Using 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 }
});

EDIT

You can do like below with pure JS:

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

These answers are all good and well and IMO @Andreas is the best, but many times in JS we have to do things asynchronously, in that case, async has you covered:

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
});

These 'times' features arent very useful for most application code, but should be useful for testing.

Assuming we can use some ES6 syntax like the spread operator, we'll want to do something as many times as the sum of all numbers in the collection.

In this case if times is equal to [1,2,3], the total number of times will be 6, i.e. 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

This post should be helpful if the logic behind constructing and spreading an array isn't apparent.

Given a function something:

function something() { console.log("did something") }

And a new method times added to the Array prototype:

Array.prototype.times = function(f){ for(v of this) for(var _ of Array(v)) f();
}

This code:

[1,2,3].times(something)

Outputs this:

did something
did something
did something
did something
did something
did something

Which I think answers your updated question (5 years later) but I wonder how useful it is to have this work on an array? Wouldn't the effect be the same as calling [6].times(something), which in turn could be written as:

for(_ of Array(6)) something();

(although the use of _ as a junk variable will probably clobber lodash or underscore if you're using it)

2

Using Array.from and .forEach.

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

TypeScript Implementation:

For those of you who are interested in how to implement String.times and Number.times in a way that is type safe and works with the thisArg, here ya go:

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(() => {})
}

A link to the TypeScript Playground with some examples can be found here

This post implements solutions posted by: Andreas Bergström, vinyll, Ozay Duman, & SeregPie

Just thought I'd add, there is a nifty JS method called .repeat(n) which will repeat a string 'n' number of times. So if you're looking for something to repeat a string 'n' number of times...

function repeatString (number, string) { return string.repeat(number);
}

So if you did...

repeatString(3, 'Hey there! ');

You'd get: 'Hey there! Hey there! Hey there! '

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like