7

假设您要检查用户在表单字段中输入的输入字符串。哪一种方法是根据可能值列表检查此输入的最快方法?

以下示例使用jQuery

第一种方法:使用||

if (input == "firstValue" || input == "secondValue" || ... ) {
    ...
}

第二种方法:使用inArray()

if ($.inArray(input, array) >= 0) {
    ...
}

这两种方法之间有什么显着差异吗?

4

4 回答 4

17

你不想要最快但最易读的方式。这就是in_array()(JavaScript: array.indexOf(value) >= 0) 超过 2 或 3 个值。

性能差异可以忽略不计——虽然函数调用和数组创建肯定有一些开销,但与文件访问、数据库访问、网络访问等昂贵的操作相比,这并不重要。所以最终没有人会注意到差异.

这是一个简短的基准,每个都有 100 万次迭代:

5.4829950332642 - in_array, the array is recreated everytime
2.9785749912262 - in_array, the array is created only once
0.64996600151062 - isset(), the array way created only once and then the values were turned to keys using array_flip()
2.0508298873901 - ||

所以,最快但仍然非常易读的方式是这个。除非您$arr只创建一次并多次使用它否则没有必要这样做,您可以简单地使用in_array().

$arr = array_flip(array('your', 'list', 'of', 'values'));
if(isset($arr[$value])) ...

如果您确实要求使用 JavaScript(在这种情况下摆脱那些$前缀!),最好的解决方案是使用Array.indexOf()

['a', 'b', 'c'].indexOf(value) >= 0

然而,并不是所有的浏览器都已经支持Array.indexOf(),所以你可能想使用 Underscore.js 中的函数

_.contains(['a', 'b', 'c'], value)

jQuery 也有一个功能:

$.inArray(value, ['a', 'b', 'c'])

最快的方法是使用对象和in运算符,但对象定义的可读性不如数组定义:

value in {'a':0, 'b':0, 'c':0}

这是各种解决方案的 JSPerf 基准测试:http://jsperf.com/inarray-vs-or -但同样,在大多数情况下,相当大的性能差异可以忽略不计,因为您不会在一次代码中执行数百万次环形。

于 2012-05-07T08:42:19.937 回答
4

答案是,这取决于...

如果只有几种可能性,请使用if (a || b || c).

如果可能多达 10 个,请使用Array.indexOf()

请注意,对于上面的两个建议,选择应该取决于可读性,而不是真正的性能。

如果有(很多)更多,请使用Object与值相等的键,然后您可以使用if (myVar in myKeyObj). 这应该给出最差的O(log n)性能。

于 2012-05-07T08:42:06.523 回答
2

执行 javascript 时,性能通常不是什么大问题,而且通常是很难回答的问题。

在此示例中,解决方案之间的主要区别在于缩放。第一个解决方案将始终进行预定数量的比较,inArray 解决方案的扩展性更差,因为如果有更多的值,它将进行更多的比较。

但是我仍然会选择 inArray,99.99% 的机会表现真的无关紧要。你想让你的代码保持可维护性,这更重要。

于 2012-05-07T08:42:18.577 回答
2

在大多数语言中,inArray() 是这样实现的:

function inArray(needle, haystack) {
  for (i = 0; i < length; i++) {
    if (haystack[index] == needle) {
      return true;
    }
  }

  return false;
}

如果你要展开那个循环,你最终会做

if (haystack[0] == needle) {
  return true;
} 
if (haystack[1] == needle) {
  return true;
}
if (haystack[3] == needle) {
  return true;
}
// and so on

可以浓缩为

if (haystack[0] == needle || haystack[2] == needle || … ) {
  return true;
}

在不改变引擎盖下发生的事情的情况下。


如果您反复查找类似的东西,我建议您了解地图。代替

var haystack = ['hello', 'world', 'how', 'is', 'life'];
if (inArray("life", haystack)) {
  // …
}

你做

var haystack = {'hello' : true, 'world' : true, 'how' : true, 'is' : true, 'life' : true};
if (haystack["life"]) {
  // …
}

必须检查的元素越多,与数组相比,地图的性能就越好。

于 2012-05-07T08:55:07.543 回答