36

In JavaScript, how can I repeat an array which contains multiple elements, in a concise manner?

In Ruby, you could do

irb(main):001:0> ["a", "b", "c"] * 3
=> ["a", "b", "c", "a", "b", "c", "a", "b", "c"]

I looked up the lodash library, and didn't find anything that was directly applicable. Feature request: repeat arrays. is a feature request for adding it to lodash, and the best workaround given there is

const arrayToRepeat = [1, 2, 3];
const numberOfRepeats = 3;
const repeatedArray = _.flatten(_.times(numberOfRepeats, _.constant(arrayToRepeat)));

The questions Most efficient way to create a zero filled JavaScript array? and Create an array with same element repeated multiple times focus on repeating just a single element multiple times, whereas I want to repeat an array which has multiple elements.

Using reasonably well-maintained libraries is acceptable.

8 Answers 8

33

No need for any library, you can use Array.from to create an array of arrays you want repeated, and then flatten using [].concat and spread:

const makeRepeated = (arr, repeats) =>
  [].concat(...Array.from({ length: repeats }, () => arr));
  
console.log(makeRepeated([1, 2, 3], 2));

On newer browsers, you can use Array.prototype.flat instead of [].concat(...:

const makeRepeated = (arr, repeats) =>
  Array.from({ length: repeats }, () => arr).flat();
  
console.log(makeRepeated([1, 2, 3], 2));

Sign up to request clarification or add additional context in comments.

2 Comments

you can make the code more concise if the repeats argument is changed to length :p
I did that originally but I thought it made the intent slightly less clear
18

You can use the Array constructor along with its fill method to fill it a number of times of the array you want to repeat, then concat them (the subarrays) into a single array:

const repeatedArray = [].concat(...Array(num).fill(arr));

Note: On older browsers (pre-ES6), you can use Function#apply to mimic the rest syntax above (concat will be called with each of the sub arrays passed to it as argument):

var repeatedArray = [].concat.apply([], Array(num).fill(arr));

Example:

const arrayToRepeat = [1, 2, 3];
const numberOfRepeats = 3;

const repeatedArray = [].concat(...Array(numberOfRepeats).fill(arrayToRepeat));

console.log(repeatedArray);

Comments

13

const repeat = (a, n) => Array(n).fill(a).flat(1)

console.log( repeat([1, 2], 3) )


Recursive alternative:

const repeat = (a, n) => n ? a.concat(repeat(a, --n)) : [];

console.log( repeat([1, 2], 3) )

Comments

8

My first idea would be creating a function like this

let repeat = (array, numberOfTimes) => Array(numberOfTimes).fill(array).reduce((a, b) => [...a, ...b], [])
console.log(repeat(["a", "b", "c"], 3))

using the fill method and reduce

Ideally, instead of using reduce you could use flatten but there's yet no support in browsers

1 Comment

Edited - added the default value for that case
4

Try

Array(3).fill(["a", "b", "c"]).flat()

console.log( Array(3).fill(["a", "b", "c"]).flat() );

Comments

1

Apart from the obvious [].concat + Array.from({length: 3}, …)/fill() solution, using generators will lead to elegant code:

function* concat(iterable) {
    for (const x of iterable)
        for (const y of x)
            yield y;
}
function* repeat(n, x) {
    while (n-- > 0)
        yield x;
}

const repeatedArray = Array.from(concat(repeat(3, [1, 2, 3])));

You can also shorten it to

function* concatRepeat(n, x) {
    while (n-- > 0)
        yield* x;
}

const repeatedArray = Array.from(concatRepeat(3, [1, 2, 3]));

Comments

1

Though other methods works simply, these too.

Array.fill() and Array.from() in previous methods will not work in IE. MDN Docs for Reference

Mehtod 1 : Loop and push (Array.prototype.push) the same into the array.

function mutateArray(arr,n)
{
    var temp = [];
    while(n--) Array.prototype.push.apply(temp,arr);
    return temp;
}
var a = [1,2,3,4,5];
console.log(mutateArray(a,3));

Method 2: Join the array elements and String.repeat() to mutate the string and return the split string.

Note: The repeat method is not supported yet in IE and Android webviews.

function mutateArray(arr,n)
{
    var arr = (arr.join("$")+"$").repeat(n).split("$");
    arr.pop(); //To remove the last empty element
    return arr;
}
var a = [1,2,3,4,5];
console.log(mutateArray(a,3));

Comments

0

Unfortunately, it is not possible natively in JS (Also operator overloading is not possible, so we can not use something like Array.prototype.__mul__), but we can create an Array with the proper target length, fill with placeholders, then re-map the values:

const seqFill = (filler, multiplier) => 
  Array(filler.length * multiplier)
  .fill(1)
  .map(
    (_, i) => filler[i % filler.length]
  );

console.log(seqFill([1,2,3], 3));
console.log(seqFill(['a','b','c', 'd'], 5));

Or another way by hooking into the Array prototype, you could use the syntax of Array#seqFill(multiplier), this is probably the closest you can get to ruby syntax (rb can do basically everything with operator overloading, but JS can't):

Object.defineProperty(Array.prototype, 'seqFill', {
  enumerable: false,
  value: function(multiplier) {
    return Array(this.length * multiplier).fill(1).map((_, i) => this[i % this.length]);
  }
});

console.log([1,2,3].seqFill(3));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.