Papageno
Papageno

Reputation: 149

How do I create a new JavaScript array without destroying the original array?

I never seem to understand JavaScript fully. Please explain this to me.

I have an array of objects called arr1. In this simplified example, it has only two members; name and someValue. The array is sorted by name and the content looks like this:

Harry   1
Joe     2
Joe     3
Peter   4

I want to create another array called arr2. It should hold the unique names from arr1. If a duplicate is found, the someValue is added for that name. I basically want this as content in arr2:

Harry   1
Joe     5 <-- the two values from Joe in arr1 sums up to 5
Peter   4

So I came up with the script below. The resulting arr2 is exactly what I want. However, the arr1 is also updated and that's not what I desire.

Why is this happening and how can I fix it?

var arr1 = [];
var arr2 = [];

arr1.push({name: 'Harry', someValue: 1});
arr1.push({name: 'Joe', someValue: 2});
arr1.push({name: 'Joe', someValue: 3});
arr1.push({name: 'Peter', someValue: 4});

let previousName = '';

for (var i=0;i<arr1.length;i++) {
  if (arr1[i].name == previousName) {
    arr2[arr2.length-1].someValue += arr1[i].someValue;
  } else {
    arr2.push(arr1[i]);
    previousName = arr1[i].name;
  }
}

/* Result arr1 is not ok:
0: Object { name: "Harry", someValue: 1 }
1: Object { name: "Joe", someValue: 5 } <-- I want the value 2 to be preserved
2: Object { name: "Joe", someValue: 3 }
3: Object { name: "Peter", someValue: 4 }

   Result arr2 is ok:
0: Object { name: "Harry", someValue: 1 }
1: Object { name: "Joe", someValue: 5 }
2: Object { name: "Peter", someValue: 4 }
*/

Upvotes: 1

Views: 1324

Answers (3)

manujamming
manujamming

Reputation: 33

Thing is when you modify those values, as they are references, mean that they are connected, they are pointing to the same memory location where it keeps the value. Creating a duplicate, but separate array a2 such that changing a1[k] will not cause a2[k] to match the modified a1[k] requires cloning.

Shallow copies can be done using a simple loop or slicing. JSON.parse and JSON.stringify creates deep copies.

This link will explain you deeper why and how to solve it. How to clone an array in JavaScript

Upvotes: 2

StepUp
StepUp

Reputation: 38164

It happens because arrays and objects are reference types. So when you are editing a reference , then it means that all objects will be edited.

So try to use spread operator to create brand new object:

arr2.push({...arr1[i]});

or Object.assign:

arr2.push(Object.assign({}, arr1[i]));

Upvotes: 3

Martin
Martin

Reputation: 16433

This is because you are pushing the object instance from arr1 onto arr2, instead of a copy.

Instead, simply create a new instance of the object when pushing onto arr2 and you will correct the problem.

Replace this line (which pushes the instance from arr1 onto arr2:

arr2.push(arr1[i]);

With this line (which creates a new instance and pushes it onto arr2:

arr2.push({name: arr1[i].name, someValue: arr1[i].someValue});

Here's a working snippet showing this:

var arr1 = [];
var arr2 = [];

arr1.push({name: 'Harry', someValue: 1});
arr1.push({name: 'Joe', someValue: 2});
arr1.push({name: 'Joe', someValue: 3});
arr1.push({name: 'Peter', someValue: 4});
;
let previousName = '';

for (var i = 0; i < arr1.length; i++) {
  if (arr1[i].name == previousName) {
    arr2[arr2.length - 1].someValue += arr1[i].someValue;
  } else {
    arr2.push({name: arr1[i].name, someValue: arr1[i].someValue});
    previousName = arr1[i].name;
  }
}

console.log(arr1);
console.log(arr2);

Upvotes: 3

Related Questions