Home > Enterprise >  TypeScript: Modifying copy of list of dictionary without mutation
TypeScript: Modifying copy of list of dictionary without mutation

Time:09-30

I have gone through several of the answers and I gather that this might be a logical error but I am not able to figure a way to achieve this.

I have to list of dictionaries in typescript/javascript. One is a copy of the other for tracking. When I am modifying one of the lists the other one gets modified too. Kindly explain a possible way to achieve the same

  var a = new Array({"x":[2,3,14,5,7,8],"y":[7,8,9,10]})
//
  var b = a.slice();
//I have tried different ways of slicing as well; for example: b = [...a]
b.filter(i=> i['x']= i['x'].filter(z=>z%2==0))
console.log(a,b)

This code modifies both the lists a and b. I want to achieve modification of b without affecting a is it possible?

CodePudding user response:

This happens because the object {"x":[2,3,14,5,7,8],"y":[7,8,9,10]} actually only exists once in your code. This one specific object is present in two different arrays. This means when you edit this object, the changes will be reflected in both arrays.

You can verify this by doing a[0] === b[0]. This results in true, because the reference to this object is identical: they are literally the same object as opposed two objects that happen to contain the exact same data.

There are two common approaches for this problem:

A deep copy is the simplest solution for this particular case. This recreates the array and even though the data appears to be the same, they are actually different objects. The simplest way of doing this is by using var b = JSON.parse(JSON.stringify(a)). Keep in mind this may not always work, as circular structures will cause an error and functions will be lost.

The second approach is to work in an immutable way, ie. creating new objects instead of modifying existing ones. There are a lot of libraries that help with this, such as 'immutability-helper' or 'immutable.js'. You can also solve this without libraries, but sometimes it results in ugly code. Example

var b = a.map(obj => ({ ...obj, x: obj.x.filter(numbers => numbers % 2 === 0)}))

We create new objects and arrays containing the values we want, instead of mutating it to the values that we want. ...obj gives us a shallow copy of the object, and then we replace the x property with a completely new array (ie. not mutated) with the filtered data.

CodePudding user response:

You need to make a deep-copy of the source

There are different ways to create a deep-copy: e.g. check this Deep copy an array in Angular 2 TypeScript

a simple way is to convert to JSON and back

var b = JSON.parse(JSON.stringify(a));

CodePudding user response:

You can try this:

var a = new Array({"x":[2,3,14,5,7,8],"y":[7,8,9,10]})
var b = JSON.parse(JSON.stringify(a));

b.filter(i=> i['x']= i['x'].filter(z=>z%2==0))
console.log(a,b)

  • Related