javascript:快速 Array.contains(otherArray)?
我有一个数组的数组。内部数组有 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 位整数数学可以让这个速度更快?
I have an array of arrays. The inner array is 16 slots, each with a number, 0..15. A simple permutation.
I want to check if any of the arrays contained in the outer array, have the same values as
a test array (a permutation of 16 values).
I can do this easily by something like so:
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;
}
But is there a faster way?
Can I assign each permutation an integral value - actually a 64-bit integer?
Each value in a slot is 0..15, meaning it can be represented in 4 bits. There are 16 slots, which implies 64 total bits of information.
In C# it would be easy to compute and store a hash of the inner array (or permutation) using this approach, using the Int64 type. Does Javascript have 64-bit integer math that will make this fast?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这已经是最快的了,在 javascript 中比较数组(就像在其他语言中一样)是相当痛苦的。我假设在执行内部循环之前比较长度无法获得任何速度优势,因为您的数组具有固定大小?
我能想到的唯一“优化”是简化语法,但它不会给你带来任何速度上的好处。您已经尽一切努力尽早返回。
您使用 64 位整数的建议听起来很有趣,但由于 javascript 没有 Int64 类型(据我所知),这将需要更复杂的东西,并且在实际使用中实际上可能比您当前的方法更慢。
That's just about as fast as it gets, comparing arrays in javascript (as in other languages) is quite painful. I assume you can't get any speed benefits from comparing the lengths before doing the inner loop, as your arrays are of fixed size?
Only "optimizations" I can think of is simplifying the syntax, but it won't give you any speed benefits. You are already doing all you can by returning as early as possible.
Your suggestion of using 64-bit integers sounds interesting, but as javascript doesn't have a Int64 type (to my knowledge), that would require something more complicated and might actually be slower in actual use than your current method.
如何比较
myInnerArray.join('##') == myCompareArray.join('##');
的字符串值(当然后一个连接应该完成一次并存储在变量中) ,而不是每次迭代都这样)。我不知道实际的性能差异是什么,但代码会更简洁。如果您多次进行比较,则可以将这些值保存在某个地方,并且至少第二次比较可能会更快。
这里明显的问题是比较容易出现误报,请考虑
但是如果您可以充分依赖您的数据,您可能可以忽略这一点?否则,如果您总是比较连接结果和长度,这不会成为问题。
how about comparing the string values of
myInnerArray.join('##') == myCompareArray.join('##');
(of course the latter join should be done once and stored in a variable, not for every iteration like that).I don't know what the actual performance differences would be, but the code would be more terse. If you're doing the comparisons a lot of times, you could have these values saved away someplace, and the comparisons would probably be quicker at least the second time round.
The obvious problem here is that the comparison is prone to false positives, consider
But if you can rely on your data well enough you might be able to disregard from that? Otherwise, if you always compare the join result and the lengths, this would not be an issue.
您真的在外部数组中寻找特定的数组实例吗?也就是说,如果
inner
匹配,它会与匹配的嵌套数组共享相同的引用吗?如果是这样,您可以跳过内部比较循环,只需执行以下操作:如果您不能这样做,您仍然可以通过不在每次循环迭代中引用 .length 字段来取得一些进展 - 这是一个昂贵的引用,因为每次引用时都会重新计算长度。
另外,我见过有人声称这种形式的循环速度更快,但我还没有看到它产生可测量差异的情况:
编辑:不,不要删除
equal< /代码> 变量;对我来说这是一个坏主意。
Are you really looking for a particular array instance within the outer array? That is, if
inner
is a match, would it share the same reference as the matched nested array? If so, you can skip the inner comparison loop, and simply do this:If you can't do this, you can still make some headway by not referencing the .length field on every loop iteration -- it's an expensive reference, because the length is recalculated each time it's referenced.
Also, I've seen claims that loops of this form are faster, though I haven't seen cases where it makes a measurable difference:
EDIT: No, don't remove the
equal
variable; that was a bad idea on my part.我唯一的想法是将循环推入实现中,并用一些内存换取(推测,你必须测试假设)速度增益,这也依赖于不可移植的 Array.prototype。{ toSource,地图}:
the only idea that comes to me is to push the loop into the implementation and trade some memory for (speculated, you'd have to test the assumption) speed gain, which also relies on non-portable
Array.prototype.{toSource,map}
:Knuth–Morris–Pratt 算法
Rumtime:O(n),n = 干草堆的大小
http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm
Knuth–Morris–Pratt algorithm
Rumtime: O(n), n = size of the haystack
http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm