Replicate Array Of Arrays And Modify Same Element Of Each Sub-Array

128 views Asked by At

I am trying to replicate an array of arrays and then modify the same element of each sub-array.

The following code is used to replicate the initial array of arrays:

const array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
const n = 2;  // replicate twice
let replicated_arrays = [];
for (let i = 0; i < n; i++) {    
    replicated_arrays.push(array);
}
replicated_arrays = [].concat.apply([], replicated_arrays);  // flatten to make one array of arrays 

The following code is then used to modify the second element of each array:

const init = 10;
replicated_arrays.forEach(function(element, index, entireArray) {
    entireArray[index][1] = init + index;
});

The desired output is:

[[1, 10, 3], [4, 11, 6], [7, 12, 9], [1, 13, 3], [4, 14, 6], [7, 15, 9]]

However, the above code produces the following:

[[1, 13, 3], [4, 14, 6], [7, 15, 9], [1, 13, 3], [4, 14, 6], [7, 15, 9]]

The forEach updates properly if the replicated array is created manually:

let replicated_arrays = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 2, 3], [4, 5, 6], [7, 8, 9]];

I therefore suspect it has something to do with the push method creating a reference to both instances of the initial array such that the final set of values (13, 14, and 15) are applied to both instances.

As an alternative to the push method, I tried the map method (e.g., in accordance with Duplicate an array an arbitrary number of times (javascript)), but it produced the same result.

Any insight or suggestions as to what is going on or how to make it work properly would be appreciated.

2

There are 2 answers

1
Nina Scholz On BEST ANSWER

You need to take copies of the inner arrays, because you need to lose the same object reference.

For pushing, you could spread the array and omit flattening later.

const array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
const n = 2;  // replicate twice
let replicated_arrays = [];
for (let i = 0; i < n; i++) {    
    replicated_arrays.push(...array.map(a => a.slice())); // spread array
}
// no need for this! replicated_arrays = [].concat.apply([], replicated_arrays);

const init = 10;
replicated_arrays.forEach(function(element, index) {
    element[1] = init + index; // access element directly without taking the outer array
});

console.log(replicated_arrays);

1
Omprakash Sharma On

Instead of concat use reduce method will keep same reference.

const array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
const n = 2;  // replicate twice
let replicated_arrays = [];
for (let i = 0; i < n; i++) {    
    replicated_arrays.push(array);
}
replicated_arrays = replicated_arrays.reduce(function(a, b){
   return a.concat(b);
}, []);

replicated_arrays.forEach((_ae,i) => {
   _ae[1] = 10 + i;
})
console.log(replicated_arrays);
output: [[1, 10, 3], [4, 11, 6], [7, 12, 9], [1, 13, 3], [4, 14, 6], [7, 15, 9]]