前言
刷算法题的时候,遇到一个需求,需要创建一个指定 n x n,指定值为 0 的多维数组,这还不简单,哼~
let n = 5;
let multiArray = Array(n).fill(Array(n).fill(0));
咋一看好像没啥问题,结果最终问题就出在创建数组这!!!
看代码,我修改其中一个元素的值:
multiArray[0][0] = "AlwaysWM";
console.log(multiArray);
输出是啥呢?
从结果中可以看出来,外层的3个数组元素指向了同一个数组,所以我改变其中一个内层数组的值,其他数组值也同步修改了,所以想要进行二维数组的初始化,不能这么做!!!
或许是因为数组没有通过 new 出来的原因?修改代码如下:
let n = 5;
let multiArray = new Array(n).fill(new Array(n).fill(0));
结果还是一样的…
我翻阅了 MDN 和一些文档,暂时不知为什么会这样,如果有知道的小伙伴,请在留言区帮忙解答下~
for
尽管这样,我们还是要想办法解决呀,最简单粗暴的方法,就是 for 循环了:
const arr = [], n = 5;
for (let i = 0; i < n; i++) {
arr[i] = [];
for (let j = 0; j < n; j++) {
arr[i][j] = 0;
}
}
map
既然是循环,当然少不了 map 了~
let n = 5;
const arr = new Array(n).fill(0).map(() => new Array(n).fill(0));
Array.from
我们也可以通过类数组来实现多维数组的创建,
Array.from 能将一个类数组或可迭代对象转换成真实的数组,可以给第二个参数传递一个函数来修改新数组的元素,就像 map 一样,
关于类数组,只要是有 length 属性的对象,就被视为类数组,
let n = 5;
const arr = Array.from({length: n}, () => Array.from({length: n}, () => 0));
优化
上面 for 循环的代码太长,而 map 和 Array.from 的代码不宜阅读,写起来很爽,同事可能就会骂娘了,作为一个优秀的程序员,必须让自己的代码像诗一样~
在 Java 中,我们定义一个二维数组很方便,也很简单明了:
int arr[5][5];
所以,我就想实现一个函数,简单明了地创建与设置多维数组的初值。
Proxy
let root = []
let tile = [root]
// 拦截器
const handers = {
get(target, key) {
key = parseInt(key)
if (key <= 0) {
try {
let res = JSON.stringify(root[0])
res = res.replaceAll('null', Math.abs(key))
return JSON.parse(res)
} finally {
root = []
tile = [root]
}
} else {
const next = []
for (const two of tile) {
for (let i = 0; i < (two.length || 1); i++) {
const one = new Array(key)
two[i] = one
next.push(one)
}
}
tile = next
}
return int
},
}
// 用 proxy 创建 int
const int = new Proxy({}, handers)
至此,我们就可以像 Java 一样,简单明了的定义多维数组了:
const arr = int[10][10][0] // 10*10 初值为 0 的数组