编辑:由于任何递归解决方案都将有一个可以创建的数组大小限制...我在我的
GitHub上的 PJs 库中提供了另一种解决方案。这个解决方案运行速度几乎瞬间,可以创建和管理任何大小、任何结构、任何维度的多维数组,并且可以模拟预填充和/或使用自定义设计的节点对象。请在这里查看:https://github.com/PimpTrizkit/PJs/wiki/14.-Complex-Multidimensional-Object--(pCMO.js)。
使用 jfabrizio 的修改版解决方案:
function createNDimArray(dimensions) {
var t, i = 0, s = dimensions[0], arr = new Array(s);
if ( dimensions.length < 3 ) for ( t = dimensions[1] ; i < s ; ) arr[i++] = new Array(t);
else for ( t = dimensions.slice(1) ; i < s ; ) arr[i++] = createNDimArray(t);
return arr;
}
用法:
。
var arr = createNDimArray([3, 2, 3])
// arr = [[[,,],[,,]],[[,,],[,,]],[[,,],[,,]]]
console.log(arr[2][1])
console.log("Falsy = " + (arr[2][1][0]?true:false) ); // Falsy = false
我发现这种方法更快。我可能会说这是在JavaScript中生成N维数组可能的最快的方式。上面的重构有一些很好的速度提升。但是,当然,最好的速度提升来自于不预填充。这个版本不预填数组。它只返回一个完全创建的N维数组,其中每个长度为N的最后一层都是一个空数组。我希望如果你真的需要null值,
arr[x] [y] [z]? arr[x] [y] [z]:null
就足够了。对我的用途来说是这样的。 :)
如果您需要预填充,请使用原始版本。
而且,如果您不在乎我所做的事情,那么请停止阅读。
想要更多的极客话题吗?下面是关于递归的一些小技巧,供那些正在学习的人参考。当进行深度递归时,请记住最后一层。它是大部分工作完成的地方。在这种情况下,它就是第N维度,字面意思上就是你的“有效载荷”,其余部分则是后勤。在jfab的函数中,当
dimensions.length
变成
1
时,它是最后一维,也是第N维,并执行有效载荷。这就是创建空数组的任务,或者在我的例子中,是一个空数组。由于递归的深度很深,每个维度都是上一个维度的因素。当你到达第N维度时,你将有许多函数调用,而后勤对计算机来说变得繁琐。在第N维度,你将为有效载荷调用基本递归函数(在我们的例子中是
createNDimArray
)比为后勤调用的次数多。现在,就像jfab的原始解决方案一样,如果可能的话,将有效载荷的执行放在递归的最前面通常是一件好事,特别是如果它很简单。在这里,通过将有效载荷设置为最终2D数组的构建(而不仅仅是通过返回
new Array()
来创建1D数组),现在不必在此级别上进行过多的函数调用。当然,如果你想预填充数组,则这种快捷方式并不总是有效。但更重要的是,预填充数组将成为适当的有效载荷。通过
不访问第N维度上的每个项目,我们实际上已经删除了它。这样就少了一层函数调用,基本上第N维度的有效载荷实际上是在第N-1个维度上完成的。而且我们永远不会再次调用递归函数,只是为了提供
new Array()
。不幸的是,对于
new Array(x)
的调用(通常情况下)并不是这样。它的执行时间随着更大的
x
而增加。这实际上仍然相当于访问第N维度上的每个项目,但现在我们只需要一次,并使用本地代码和包装在紧凑而轻巧的循环中。现在,我们要求
createNDimArray
只能被调用N > 1,即永远不要用来创建1D数组。理论上,你可以要求更大的N,并在最后展开更多的维度。基本上,具有
if ( dimensions.length < 3 )
的行将读取类似于
<4
或
<5
的内容,然后你需要在已经存在的循环周围包装那么多额外的
for
循环,它们都需要自己的一组
var
--- 所以我不确定它是否非常高效,因为你正在用过多的函数调用和堆栈空间/操作来交换一个类似的想法,但是嵌入式的
for
循环。但我想如果你知道N始终在某个水平以上或者仅适用于最终维度,那么它可能会加速某些环境
下一步就是修改他的解决方案,只是物流方面的问题,只需简单重构以消除过多的块和代码,将所有的
var
工作合并在一起即可。由于需要返回一个
arr
,所以一旦循环结束,最好先在一行上完成所有的
var
工作,幸运的是,四个
var
中有三个具有相同的初始化。请记住,如果可能的话,Javascript可以通过逗号优化代码的连接。这也使得代码更加紧凑。
a[2][3][5]
来代替getElement(a, [2, 3, 5])
。 - sk29910a[index1][index2][index3]
? - sk29910a[index1]
或a[index][index2]
。 - Barmar