重置多维数组的最快方法?

时间:2012-11-07 18:27:05

标签: javascript arrays performance algorithm multidimensional-array

假设我有一个二维数组:vectors[x][y],初始数组结构如下所示:

vectors = [    
 [0, 0, 0, 0, 0,],
 [0, 0, 0, 0, 0,],
 [0, 0, 0, 0, 0,],
 [0, 0, 0, 0, 0,],
 [0, 0, 0, 0, 0,]
]

经过一些计算,数组中的数据是随机的。将数组返回到初始状态的最快方法和最有效的方法是什么?

我知道我可以硬编码上面的归零数组并再次设置等于它的向量,但我也知道一个算法如:

for (var x = 0; x < vectors.length; x++) {
    for (var y = 0; y < vectors[x].length; y++) {
        vectors[x][y] = 0;
    }

}

是O(x * y)。

那么哪种方式更好?是否有更好,更快/更有效的方法来解决这个问题?

对于将任意长度的多维数组归零的一般情况,这是最好的方法吗? (如果重要,我正在使用JavaScript)

5 个答案:

答案 0 :(得分:3)

这是我的两分钱:

我会保留原始阵列的干净副本以获得最快的性能。您可以保留引用的硬编码副本

var vectorsOrig = [    
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0]
];

或使用slice执行初始数组的动态清理克隆((在您的情况下递归进行深层复制):

var clonedVectors = [0, 0, 0, 0, 0].slice(0);

无论如何,采用将矢量引用重置为原始副本的方法将比循环和重置每个节点更快。如果您的旧向量数组对象不再被引用,JavaScript将垃圾收集它。

话虽如此,问题变得每次都获得一份干净的副本。有一次硬编码的实例会给你一个干净的副本,你将不得不克隆它。您也不希望通过类似for循环的动态生成作为重置选项。我的建议是编写一个只返回一个新的硬编码或初始化数组的克隆函数:

function newVector() {
    return [    
     [0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0]
    ];
}
var vector = newVector();
vector[1][2] = 11;
console.dir(vector);
vector = newVector();  // your old array will be garbage-collected if no longer referenced by any other reference
console.dir(vector);

理想情况下,最好对各种方法进行基准测试。

修改 感谢Vega的意见,我修改了他的测试以测试三种方法。在Chrome和IE9中,这个解决方案似乎是最快的,在FF(15.0.1)手动迭代看起来更快(可能在FF中内存分配/管理较慢)。 http://jsperf.com/array-zero-test/2

答案 1 :(得分:1)

到目前为止,听起来我们有两种可能的选择。

  1. 用零覆盖整个事物。 (您的解决方案)

  2. 记录所有已修改的元素,并仅重置这些元素。 record[0].x = 3; record[0].y = 5;等等 但是,您仍然需要在记录中循环一次。 为了进一步解释,我的意思是每次将数组中的元素设置为值时,都应该记录该元素在数组中的位置。然后,使用循环,您可以访问每个元素并将其设置为0.因此,如果您有一个稀疏数组,它将更有效。

  3. 根据实施情况,我可以看到为什么你想要#2而不是#1 ......但如果你真的有足够大的矩阵需要担心分析算法,你可能会考虑做某种服务器预处理。

答案 2 :(得分:0)

如果我是你,我会有一个空数组,每当我重置值时,我只需用空数替换变量。如果您与重新设置和初始化有很多关系,那么只需要另一个空数组。

<强>更新

也许这会帮助你顺利完成:

var empty = function() {
    return [
     [0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0]
    ];
};

var vectors = new empty();

for (var i = 0; i < 10; i++)
{
    for (var x = 0; x < vectors.length; x++)
        for (var y = 0; y < vectors[x].length; y++)
            vectors[x][y] = x * y + 2; // Some values just for changing the array.

    vectors = new empty();
}

干杯。

答案 3 :(得分:0)

我冒险说,为所有元素分配相同值的最快方法是调用Array.map()。

但是,这里有一个问题。请注意,这将在本机实现该方法的浏览器上具有令人难以置信的快速性能,并且在其他浏览器中具有通常的性能。另请注意,.map()在某些旧浏览器中不可用,因此您需要使用Underscore.js或提供该方法的任何其他库。

答案 4 :(得分:0)

另一种看待问题的不同方法是使用线性数组并在进行更新时从x,y索引计算线性索引。

然后初始化只是一个for循环,时间为O(x + y)