44

Whats the easiest way (with "native" javascript) to duplicate every element in a javascript array?

The order matters.

For example:

a = [2, 3, 1, 4]
// do something with a
a
// a is now [2, 2, 3, 3, 1, 1, 4, 4]
3
  • Not preferred/recommended/reliable but regex can also be used. a = a.join(',').replace(/(\d+)/g, "$1,$1").split(',').map(Number); Commented Oct 24, 2015 at 5:06
  • @Tushar Nice idea. However, as you already assumed, I'm looking for a generic solution that also works with arrays of strings that might even contain commas... Commented Oct 26, 2015 at 7:25
  • 3
    The top answers to this question seem to be games of complexity code golf. Don't use reduce, the intent is super unclear. Sometimes a for loop is the correct answer guys, sorry. Commented Sep 21, 2016 at 21:37

12 Answers 12

45

I came up with something similar to tymeJV's answer

[2, 3, 1, 4].reduce(function (res, current, index, array) {
    return res.concat([current, current]);
}, []);
Sign up to request clarification or add additional context in comments.

3 Comments

I don't understand why the two last parameters (index, array) are needed if I don't see them used. Can someone please explain this?
How to duplicate it 10 times?
[2,3,1,4].reduce((a,i)=>a.concat(i,i),[]) is a lot easier to read or a.concat(Array(10).fill(i)), or map if i is an an object and you need clones
38

Basically you can use flatMap in ES19

a = [1, 2, 3, 4];
a.flatMap(i => [i,i]); // [1, 1, 2, 2, 3, 3, 4, 4]

Also you can customize the repetitions number like this:

a = [1, 2, 3, 4];
const dublicateItems = (arr, numberOfRepetitions) => 
    arr.flatMap(i => Array.from({ length: numberOfRepetitions }).fill(i));

dublicateItems(a, 3);

My reply to the comment below by @user120242 why so complicated? a.flatMap(i => Array(n).fill(i)) find it here

4 Comments

You can continue answering on it. Thanks @Kaiido
why so complicated? a.flatMap(i => Array(n).fill(i))
@ZeyadEtman You mean ES10 (ES2019)?
@user120242 please check my updated answer.
17

Basically:

a = [2, 3, 1, 4];
b=[];

for(var i = 0; i< a.length;++i){
  b.push(a[i]);
  b.push(a[i]);
}

a=b;

5 Comments

If anyone wonders which is the best way, I made a benchmark and this is the fastest way to duplicate, but if you want to duplicate more than 6 times use nested loops for even more efficient duplication. (Tested on a random array with 100000 elements)
one can make it even faster if avoid to call to a.length in every step
@SergeiKovalenko do you have any benchmark on that? Because as far as I know a.length has O(1) complexity because array length should be implemented as a constant in JS. See stackoverflow.com/questions/32850662/… for further info
@morels, the benchmarks script in the page you provided shows sometimes .length 11 and var 11, but mostly .length 12 and var 10, which is the difference between the calculation and direct access to the value. but there is never .length < var
Do you have any public source? I'm genuinely interested. I cannot replicate your results because I don't know where data comes from, sorry.
6

I came across this issue in my application, so I created this function:

function duplicateElements(array, times) {
  return array.reduce((res, current) => {
      return res.concat(Array(times).fill(current));
  }, []);
}

To use it, simple pass the array, and the number of times you want the elements to be duplicated:

duplicateElements([2, 3, 1, 4], 2);
// returns: [2, 2, 3, 3, 1, 1, 4, 4]

1 Comment

ES6 version: return [...res, ...Array(times).fill(current)];
5

I suppose you could do:

var duplicated = a.map(function(item) {
    return [item, item];
}).reduce(function(a, b) { return a.concat(b) });

//duplicated: [2, 2, 3, 3, 1, 1, 4, 4]

4 Comments

Isn't Map ES6? In that case there may be compatibility issues with this solution
map + reduce + concat seems overkill. Reduce better.
@EricHerlitz -- .map is ES5.
@EricHerlitz Yes it is, but here, it is Array.prototype.map, so no problem as long as it is a standard browser or IE8+
2

ES6 way of life (based on axelduch's answer)

const arr = [2, 3, 1, 4].reduce((res, current) => [...res, current, current], []);

console.log(arr);

Comments

2

A very basic snippet by just using loops and push.

It's dynamic function, So you can specify duplicator to duplicate value number of times.

Function name duplicate

Syntax: duplicate (array, duplicator)

  • Array array to be passed in the function.
  • duplicator integer value to be passed to duplicate number of times.

How it works: function takes two parameter array and duplicator, It build new array based on duplicator and return newly built array.

Snippet

function duplicate(array, duplicator){
        var buildArray = [];
        for(i=0; i<array.length; i++){
                for(j=0; j<duplicator; j++){
                        buildArray.push(array[i]);
                }
        }
        return buildArray;
}

Usage

var a = [2, 3, 1, 4];
var result = duplicate(a, 2);
console.log(result);

Change duplicator value according to your requirement to get desired output.

Reference:

push()

Comments

1

Just splice a little bit.

var a = [2, 3, 1, 4],
    i = a.length;
while (i--) {
    a.splice(i, 0, a[i]);
}
document.write('<pre>' + JSON.stringify(a, 0, 4) + '</pre>');

Comments

1

These functions may help see .sort(), .concat()

function duplicate(arr) {
    return arr.concat(arr).sort()
} 
console.log(duplicate([1,2,3,4,5]))

1 Comment

In question its clearly mentioned The order matters.
1

how 'bout that?

for (i=a.length-1;i>=0;i--)a.splice(i,0,a[i]);

iterating backwards is undervalued, in this case it keeps the index intact ;)

Comments

-1
0/2  =  0    =  0  |0  =  0
1/2  =  0.5  =  0.5|0  =  0
2/2  =  1    =  1  |0  =  1
3/2  =  1.5  =  1.5|0  =  1
4/2  =  2    =  2  |0  =  2
5/2  =  2.5  =  2.5|0  =  2
6/2  =  3    =  3  |0  =  3
7/2  =  3.5  =  3.5|0  =  3

Treat |0 as Math.floor


In code this could look like this:

for (let i = 0; i < a.length * 2; i++) {
  a[i] = a[i / 2 | 0]
}

Because immutability is preferable, one could do something like this:

function repeatItems(a, n) {
  const b = new Array(a.length * n)
  for (let i = 0; i < b.length; i++) {
    b[i] = a[i / n | 0]
  }
  return b
}

Unreadable ES6 spaghetti code:

const repeatItems = (a, n) => Array.from(Array(a.length * n), (_, i) => a[i / n | 0])

Comments

-2

Lot of ways to add items to an array as seen above. I have compared it and you can view the performance by yourself in the console. Whatever is timed goes between the two "console.time"

console.clear();

function loopMyArray(){
 var loopArray = new Array(10000);
 for(var i = 0; i < loopArray.length; i++){
   loopArray[i] = i+1;
 }
 console.log(loopArray);
}
console.time('loopMyArray');
loopMyArray();
console.timeEnd('loopMyArray');

function fillArray(){
 let x = 0;
 let filledArray = new Array(10000).fill(null).map(()=> ++x);
 console.log(filledArray);
}

console.time('fillArray');
fillArray();
console.timeEnd('fillArray');

function keyMyArray(){
 let fromKeyArray = Array.from(Array(10000).keys());
 console.log(fromKeyArray);
}
console.time('keyMyArray');
keyMyArray();
console.timeEnd('keyMyArray');

function spreadKeysArray(){
 let spreadArray = [...Array(10000).keys()];
 console.log(spreadArray);
}
console.time('spreadKeysArray');
spreadKeysArray();
console.timeEnd('spreadKeysArray');

console.log(' Start from 1');

function mapKeyArray(){
 //let mapArray = ([...Array(1000).keys()].map(x => x++)); //increment after return
 let mapArray = [...Array(10000).keys()].map(x => ++x);
 console.log(mapArray);
}

console.time('mapKeyArray');
mapKeyArray();
console.timeEnd('mapKeyArray');

function sliceKeyArray(){
 let sliceFirstElementArray = [...Array(10000+1).keys()].slice(1);
 console.log(sliceFirstElementArray);
}
console.time('sliceKeyArray');
sliceKeyArray();
console.timeEnd('sliceKeyArray');

function calcFromLength(){
 let fromLengthArray = Array.from({length: 10000}, (v, k) => k+1);
 console.log(fromLengthArray);
}
console.time('calcFromLength');
calcFromLength();
console.timeEnd('calcFromLength');

console.log('======== add a double for every item ========');

function loopDoubleArray(){
 var first5000Array = [...Array(5000+1).keys()].slice(1);
 var double5000Array =[];

 for(var i = 0; i< first500Array.length;++i){
   double5000Array.push(first5000Array[i]);
   double5000Array.push(first5000Array[i]);
 }
 console.log(double5000Array);
}
console.time('loopDoubleArray');
loopDoubleArray(); // Whatever is timed goes between the two "console.time"
console.timeEnd('loopDoubleArray');

function mapDoubleArray(){
 // adding 1,1,2,2,3,3 etc
 let doubleArray = [...Array(10000).keys()].map(x => Math.floor(++x/2) + x%2);
 console.log(doubleArray);
}
console.time('mapDoubleArray');
mapDoubleArray();
console.timeEnd('mapDoubleArray');

function fromDoubleArray(){
 let fromDoubleArray = Array.from({length: 10000}, (v, x) => Math.floor(++x/2) + x%2);
 console.log(fromDoubleArray);
}
console.time('fromDoubleArray');
fromDoubleArray(); // Whatever is timed goes between the two "console.time"
console.timeEnd('fromDoubleArray');

function doubleSpreadArray(){
 let keyArray = [...Array(500+1).keys()].slice(1);
 let doubleSpreadArray = [...keyArray,...keyArray];
 console.log(doubleSpreadArray);
}
console.time('doubleSpreadArray');
doubleSpreadArray(); // Whatever is timed goes between the two "console.time"
console.timeEnd('doubleSpreadArray');

function reduceDoubleArray(){
 let reduceDoubleArray = Array.from({length: 5000}, (v, k) => k+1).reduce((m,i) => m.concat([i,i]), []);
 console.log(reduceDoubleArray);
}
console.time('reduceDoubleArray');
reduceDoubleArray(); // Whatever is timed goes between the two "console.time"
console.timeEnd('reduceDoubleArray');

I compared some speeds and it looks as if there are not so many differences. The speed(in ms for 10000 items) of calculation between map, slice and from are not so different (slice one seems a bit better). Using reduce in the calculation for double items array is way more slower then the rest of methods

| mapMyArray     | 5,342041016 | 5,21484375  | 8,424804688 | 5,516113281 |
| sliceKeyArray  | 5,221191406 | 4,854248047 | 6,069091797 | 4,940185547 |
| calcFromLength | 6,156005859 | 5,988037109 | 6,031982422 | 6,739990234 |

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.