javascript:speedy Array.contains(otherArray)?

时间:2010-01-01 21:43:35

标签: javascript permutation

我有一个数组数组。内部阵列是16个插槽,每个插槽的编号为0..15。一个简单的排列。

我想检查外部数组中包含的任何数组是否具有相同的值 测试数组(16个值的排列)。

我可以通过类似的方式轻松地做到这一点:

var containsArray = function (outer, inner) {
    var len = inner.length;
    for (var i=0; i<outer.length;  i++) {
        var n = outer[i];
        var equal = true;
        for (var x=0; x<len; x++) {
            if (n[x] != inner[x]) {
                equal = false;
                break;
            }
        }
        if (equal) return true;
    }
    return false;
}

但有更快的方法吗?

我可以为每个排列分配一个整数值 - 实际上是64位整数吗?

插槽中的每个值都是0..15,这意味着它可以用4位表示。有16个插槽,这意味着64位信息。

在C#中,使用Int64类型使用这种方法计算和存储内部数组(或置换)的散列很容易。 Javascript是否有64位整数数学可以使这个快速?

6 个答案:

答案 0 :(得分:0)

这个速度和它一样快,比较javascript中的数组(和其他语言一样)是非常痛苦的。我假设在进行内循环之前比较长度不能获得任何速度优势,因为你的数组是固定大小的?

我认为只有“优化”才能简化语法,但它不会给你任何速度优势。你已尽可能早地回来了。

你使用64位整数的建议听起来很有意思,但是由于javascript没有Int64类型(据我所知),这需要更复杂的东西,实际上可能比你当前的方法更慢。 / p>

答案 1 :(得分:0)

如何比较myInnerArray.join('##') == myCompareArray.join('##');的字符串值(当然后一个连接应该进行一次并存储在变量中,而不是像每次迭代那样)。

我不知道实际的性能差异是什么,但代码会更简洁。如果你正在进行很多次的比较,你可以将这些值保存在某个地方,并且比较可能会更快,至少第二次。

这里明显的问题是比较容易出现误报,请考虑

var array1 = ["a", "b"];
var array2 = ["a##b"];

但是如果你能够很好地依赖你的数据,你可能会忽视它?否则,如果您始终比较连接结果的长度,则不会出现问题。

答案 2 :(得分:0)

您是否真的在外部数组中寻找特定的数组实例?也就是说,如果inner匹配,它是否会与匹配的嵌套数组共享相同的引用?如果是这样,您可以跳过内部比较循环,只需执行此操作:

var containsArray = function (outer, inner) {
    var len = inner.length;
    for (var i=0; i<outer.length;  i++) {
        if (outer[i] === inner) return true;
    }
    return false;
}

如果你不能这样做,你仍然可以通过在每次循环迭代中不引用.length字段来取得一些进展 - 这是一个昂贵的引用,因为每次引用时都会重新计算长度。

var containsArray = function (outer, inner) {
    var innerLen = inner.length, outerLen = outer.length;
    for (var i=0; i<outerLen;  i++) {
        var n = outer[i];
        var equal = true;

        for (var x=0; x<innerLen; x++) {
            if (n[x] != inner[x]) {
                equal = false;
            }
        }
        if (equal) return true;
    }
    return false;
}

此外,我已经看到声称这种形式的循环更快,但我没有看到它产生可衡量的差异的情况:

var i = 0;
while (i++ < outerLen) {
   //...
}

编辑:不,请勿删除equal变量;这对我来说是一个坏主意。

答案 3 :(得分:0)

唯一的想法是将循环推入实现并交换一些内存(推测,你必须测试假设)速度增益,这也依赖于非可移植的Array.prototype.{toSource,map}

var to_str = function (a) {
    a.sort();
    return a.toSource();
}
var containsString = function (outer, inner) {
    var len = outer.length;
    for (var i=0; i<len;  ++i) {
        if (outer[i] == inner)
            return true;
    }
    return false;
}

var found = containsString(
    outer.map(to_str)
  , to_str(inner)
);

答案 4 :(得分:0)

var containsArray = function (outer, inner) {
    var innerLen  = inner.length, 
        innerLast = inner.length-1, 
        outerLen  = outer.length;

    outerLoop: for (var i=0; i<outerLen;  i++) {
        var n = outer[i];

        for (var x = 0; x < innerLen; x++) {
            if (n[x] != inner[x]) {
                continue outerLoop;
            }
            if (x == innerLast) return true;
        }
    }
    return false;
}

答案 5 :(得分:0)

Knuth-Morris-Pratt算法

Rumtime:O(n),n =干草堆的大小

http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm