TypeScript中使用slice()为何仍修改了原二维数组?
问题:高斯消元法中slice()复制二维数组后原数组仍被修改的原因及解决办法
我第一次用TypeScript写高斯消元(Gauss Jordan Elimination)代码,知道slice()方法能返回数组副本,所以用const input = linsys.slice()复制输入的二维数组linsys,想只修改副本、保留原数组,但控制台打印发现原数组linsys也被修改了。以下是代码片段:
class ChapterOne { // Gauss Jordan Elimination // Notes: Only solve system of linear equation with one solution static gaussJordanElim( linsys : number[][] ) { const numOfEquation = linsys.length const numOfUnknown = linsys[0].length - 1 if (numOfUnknown > numOfEquation) return 'This System of Linear Equation either have no solution or have infinite solutions' // I slice it here. const input = linsys.slice() const length = input.length // pointer = i, row to operate = j, column to operate = k for (let i = 0; i < length; i += 1) { if (input[i][i] === 0) return 'Mathematical Error! Cannot divide by zero' for (let j = 0; j < length; j += 1) { if (i !== j) { const ratio = input[j][i] / input[i][i] for (let k = 0; k < length + 1; k += 1) { input[j][k] = input[j][k] - ratio * input[i][k] } } } } // I Checked it here console.log(input) console.log(linsys) const output = input.map((row, pointer) => row[length] / row[pointer]) return output } }
原因解释
slice()方法对二维数组做的是浅拷贝:它只会复制外层数组的结构,而数组里的每个子数组(也就是每一行)都是引用类型,input和原数组linsys指向的是同一个子数组对象。当你修改input[j][k]时,实际上是在修改这个共享的子数组元素,所以原数组linsys也会跟着变化。
解决方法
要实现真正的独立副本,需要对二维数组进行深拷贝,确保每个子数组也被复制。有几种常用方式:
方法1:使用map + slice()复制每一行
把原代码里的const input = linsys.slice()替换成:
const input = linsys.map(row => row.slice())
map遍历原数组的每一行,对每一行调用slice()生成该行的副本,这样input的所有子数组都是独立的,修改时不会影响原数组。
方法2:使用JSON序列化(适合纯数值数组)
如果数组里只有数值类型,也可以用这种简单方式:
const input = JSON.parse(JSON.stringify(linsys))
注意:这种方法不适合包含函数、Symbol等特殊类型的数组,但你的场景是纯数值二维数组,完全适用。
修改后的完整代码
class ChapterOne { // Gauss Jordan Elimination // Notes: Only solve system of linear equation with one solution static gaussJordanElim( linsys : number[][] ) { const numOfEquation = linsys.length const numOfUnknown = linsys[0].length - 1 if (numOfUnknown > numOfEquation) return 'This System of Linear Equation either have no solution or have infinite solutions' // 深拷贝二维数组,确保子数组独立 const input = linsys.map(row => row.slice()) const length = input.length // pointer = i, row to operate = j, column to operate = k for (let i = 0; i < length; i += 1) { if (input[i][i] === 0) return 'Mathematical Error! Cannot divide by zero' for (let j = 0; j < length; j += 1) { if (i !== j) { const ratio = input[j][i] / input[i][i] for (let k = 0; k < length + 1; k += 1) { input[j][k] = input[j][k] - ratio * input[i][k] } } } } console.log(input) console.log(linsys) const output = input.map((row, pointer) => row[length] / row[pointer]) return output } }
内容的提问来源于stack exchange,提问作者Fritz Adelbertus Sitindaon
相关产品推荐
相关产品推荐

