do <something> N times (declarative syntax)

JavascriptJqueryunderscore.js

Javascript Problem Overview


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

Javascript Solutions


Solution 1 - Javascript

Just use a for loop:

var times = 10;

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

Solution 2 - Javascript

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

Solution 3 - Javascript

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)

Solution 4 - Javascript

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)

Solution 5 - Javascript

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

Solution 6 - Javascript

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

Solution 7 - Javascript

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

Solution 8 - Javascript

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;

Solution 9 - Javascript

How about a simple while.

let times = 5;

while (times--) {

    console.log(times+1)

}

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

Solution 10 - Javascript

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

Solution 11 - Javascript

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

Solution 12 - Javascript

const loop (fn, times) => {
  if (!times) { return }
  fn()
  loop(fn, times - 1)
}

loop(something, 3)

Solution 13 - Javascript

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

Solution 14 - Javascript

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

Solution 15 - Javascript

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

Solution 16 - Javascript

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

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

Solution 17 - Javascript

// 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 https://stackoverflow.com/a/20066663/275501 )

Array.apply(null, {length: 42}).forEach( doSomething );

Solution 18 - Javascript

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:

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

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

Solution 19 - Javascript

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.

Solution 20 - Javascript

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)

Solution 21 - Javascript

Using Array.from and .forEach.

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

Solution 22 - Javascript

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

Solution 23 - Javascript

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! '

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBreakPhreakView Question on Stackoverflow
Solution 1 - JavascriptahrenView Answer on Stackoverflow
Solution 2 - JavascriptnverbaView Answer on Stackoverflow
Solution 3 - JavascriptvinyllView Answer on Stackoverflow
Solution 4 - JavascriptvsyncView Answer on Stackoverflow
Solution 5 - JavascriptThoView Answer on Stackoverflow
Solution 6 - JavascriptggozadView Answer on Stackoverflow
Solution 7 - JavascriptOzay DumanView Answer on Stackoverflow
Solution 8 - JavascriptAndreas BergströmView Answer on Stackoverflow
Solution 9 - JavascriptPositivityView Answer on Stackoverflow
Solution 10 - JavascriptSirkoView Answer on Stackoverflow
Solution 11 - JavascriptXU3352View Answer on Stackoverflow
Solution 12 - JavascriptGoroView Answer on Stackoverflow
Solution 13 - JavascriptLior ElromView Answer on Stackoverflow
Solution 14 - JavascriptJan BodnarView Answer on Stackoverflow
Solution 15 - JavascriptthecodeparadoxView Answer on Stackoverflow
Solution 16 - JavascriptMachuView Answer on Stackoverflow
Solution 17 - JavascriptgoofballLogicView Answer on Stackoverflow
Solution 18 - JavascriptAlexander MillsView Answer on Stackoverflow
Solution 19 - JavascriptIliasTView Answer on Stackoverflow
Solution 20 - JavascriptpixView Answer on Stackoverflow
Solution 21 - JavascriptSeregPieView Answer on Stackoverflow
Solution 22 - JavascriptNoah AndersonView Answer on Stackoverflow
Solution 23 - JavascriptTravis McKinstryView Answer on Stackoverflow