TypeScript:修改字典列表的副本而不进行突变
TypeScript: Modifying copy of list of dictionary without mutation
我已经看了几个答案,我认为这可能是一个逻辑错误,但我无法想出一种方法来实现这一点。
我必须列出 typescript/javascript 中的词典。一个是另一个用于跟踪的副本。当我修改其中一个列表时,另一个列表也会被修改。请解释实现相同目标的可能方法
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)
此代码同时修改列表 a 和 b。我想在不影响a的情况下实现b的修改,可以吗?
你可以试试这个:
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)
您需要对源进行深拷贝
创建深拷贝的方法有多种:例如检查这个
一种简单的方法是转换为 JSON 并返回
var b = JSON.parse(JSON.stringify(a));
var a = new Array({"x":[2,3,14,5,7,8],"y":[7,8,9,10]})
var b = JSON.parse(JSON.stringify(a));
//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)
发生这种情况是因为对象 {"x":[2,3,14,5,7,8],"y":[7,8,9,10]}
实际上在您的代码中只存在一次。这个特定对象存在于两个不同的数组中。这意味着当您编辑此对象时,更改将反映在两个数组中。
您可以通过 a[0] === b[0]
来验证这一点。这导致 true
,因为对该对象的引用是相同的:它们实际上是同一个对象,而不是恰好包含完全相同数据的两个对象。
这个问题有两种常见的解决方法:
对于这种特殊情况,深拷贝是最简单的解决方案。这将重新创建数组,即使数据看起来相同,但它们实际上是不同的对象。最简单的方法是使用 var b = JSON.parse(JSON.stringify(a))
。请记住,这可能并不总是有效,因为圆形结构会导致错误并且功能会丢失。
第二种方法是以不可变的方式工作,即。创建新对象而不是修改现有对象。有很多库可以帮助解决这个问题,例如 'immutability-helper' 或 'immutable.js'。你也可以在没有库的情况下解决这个问题,但有时它会导致代码难看。例子
var b = a.map(obj => ({ ...obj, x: obj.x.filter(numbers => numbers % 2 === 0)}))
我们创建包含我们想要的值的新对象和数组,而不是将其变异为我们想要的值。 ...obj
给我们一个对象的浅表副本,然后我们用过滤后的数据用一个全新的数组(即未突变)替换 x
属性。
我已经看了几个答案,我认为这可能是一个逻辑错误,但我无法想出一种方法来实现这一点。
我必须列出 typescript/javascript 中的词典。一个是另一个用于跟踪的副本。当我修改其中一个列表时,另一个列表也会被修改。请解释实现相同目标的可能方法
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)
此代码同时修改列表 a 和 b。我想在不影响a的情况下实现b的修改,可以吗?
你可以试试这个:
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)
您需要对源进行深拷贝
创建深拷贝的方法有多种:例如检查这个
一种简单的方法是转换为 JSON 并返回
var b = JSON.parse(JSON.stringify(a));
var a = new Array({"x":[2,3,14,5,7,8],"y":[7,8,9,10]})
var b = JSON.parse(JSON.stringify(a));
//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)
发生这种情况是因为对象 {"x":[2,3,14,5,7,8],"y":[7,8,9,10]}
实际上在您的代码中只存在一次。这个特定对象存在于两个不同的数组中。这意味着当您编辑此对象时,更改将反映在两个数组中。
您可以通过 a[0] === b[0]
来验证这一点。这导致 true
,因为对该对象的引用是相同的:它们实际上是同一个对象,而不是恰好包含完全相同数据的两个对象。
这个问题有两种常见的解决方法:
对于这种特殊情况,深拷贝是最简单的解决方案。这将重新创建数组,即使数据看起来相同,但它们实际上是不同的对象。最简单的方法是使用 var b = JSON.parse(JSON.stringify(a))
。请记住,这可能并不总是有效,因为圆形结构会导致错误并且功能会丢失。
第二种方法是以不可变的方式工作,即。创建新对象而不是修改现有对象。有很多库可以帮助解决这个问题,例如 'immutability-helper' 或 'immutable.js'。你也可以在没有库的情况下解决这个问题,但有时它会导致代码难看。例子
var b = a.map(obj => ({ ...obj, x: obj.x.filter(numbers => numbers % 2 === 0)}))
我们创建包含我们想要的值的新对象和数组,而不是将其变异为我们想要的值。 ...obj
给我们一个对象的浅表副本,然后我们用过滤后的数据用一个全新的数组(即未突变)替换 x
属性。