js数组查找最接近_在JavaScript数组中找到最小元素的位置

在JavaScript数组中找到最小元素的位置

注*  之前有篇文章介绍过数据遍历的性能比较: for in 比for loop慢至少20倍 ,这是另外一篇比较数组查找性能的例子,通过对手工/indexOf/reduce三者的比较,再次映证,内置函数不一下比手工写的函数快。

今天的小程序甚至不是一个程序。这只是一个函数。

问题陈述如下:给定一个非空的JavaScript数字数组,找到最小值的索引。(如果最小值出现不止一次,那么任何此类索引是可以接受的。)

一个解决方案是进行简单的手动操作,模拟用纸笔如何执行操作:首先,你假设第一个元素是赢家,然后你遍历其他元素。如果你的下一个元素小于第一个元素,那么你声明这个元素是新的临时的赢家。function indexOfSmallest(a) {

var lowest = 0;

for (var i = 1; i 

if (a[i] 

}

return lowest;

}

另一种解决方案是使用reduce内联函数本质来运行循环,所以你只需要提供初始猜测和if语句的业务逻辑。function indexOfSmallest(a) {

return a.reduce(function(lowest, next, index) {

return next 

0);

}

第三个解决方案是使用JavaScript 内联函数找到最小的元素,然后将元素转换为其索引。function indexOfSmallest(a) {

return a.indexOf(Math.min.apply(Math, a));

}

哪一个最快呢?

好吧,首先,你确定哪一个是最快之前,您需要确保他们都是正确的。你发现的一件事是,一旦数组变得很大最小/索引技术会失败,至少它在IE浏览器和Firefox上是这样的。(在我的例子中,Internet Explorer和Firefox分别放弃了元素数量约为250000和500000的数组)。那是因为你开始触及引擎的数量限制参数,这个参数你可以传递给一个函数。调用250000个元素的数组相当于最少调用250000个函数参数。所以我们会限制自己的数组长度最多为250000。分享结果之前,我想让你猜猜哪个算法你认为将是最快和哪个是最慢的。

仍然在等。

我预计手工版本是最后一名,因为,毕竟,这是手工做的一切。我预计使用减少函数的版本稍快,因为它把一些工作交给了内联函数(尽管上面的函数调用可能否定了它的改进)。我预计min/ indexOf版本是最快的,因为几乎所有的工作在内联函数中完成,并且两次数据遍历的开销将会由内联函数的一些改进性能构成。

这里有三个版本在不同大小的数组上的计时,它是运行在随机数据上。我正常运行了好几次,所以这个结果与CPU速度是独立的。

每个数组元素相对运行时间元素手工reducemin/indexOf

Internet Explorer 9

100,0001.0002.1552.739

200,0001.0142.3243.099

250,0001.0232.2002.330

Internet Explorer 10

100,0001.0004.0574.302

200,0001.0284.0574.642

250,0001.0194.0914.068

你感到惊讶吗?我肯定我很惊讶!

我不仅完全向后又运算了一遍,但手工版本胜利的界限的是超出了我的想象的。

(这表明要知道程序的性能,唯一途径肯定是坐下来测量它。)

我认为正在发生的是,JavaScript优化器可以很好地优化手工代码,因为它非常简单。 循环体没有函数调用,只是一行,在外面没关系的。使用内联函数的版本以从优化器隐藏一些信息结束。(毕竟,优化器不能提前预测是否有人覆盖Array.prototype.reduce或者Math.prototype.min的默认实现,所以不能盲目的内联调用。)结果是,在IE9浏览器上运行手动版本可以快两倍,在IE10上运行速度超过四倍。

我弄错了,因为我想起了JavaScript太像一种解释型语言。在一个纯粹的解释型语言,翻译的开销大约与你让它做的事情的数量成正比,而不是与做这些事情是多么难成正比。就像一个对每一笔交易固定的服务费,不管交易是100美元50美分。你因此试图做一笔大的买卖(调用复杂的内联函数)而不是大量的小买卖(读一个数组元素,比较两个值,增加一个变量,一个变量复制到另一个)。

福利:我在Firefox上做了这个测试,因为我碰巧比较方便。

每个数组元素相对运行时间元素手工reducemin/indexOf

Firefox 16

100,0001.00021.5983.958

200,0000.84821.7012.515

250,0000.83921.7882.090

相同的数据收集在Firefox 16(这听起来是可笑的老旧版本,因为到这篇文章到达队列头部的时候,Firefox将发行523版本)展示了一个不同的形象,尽管胜利者是相同的。数组大小增加的时候手动循环和min/ indexOf变得更高效。这表明,当你增加数据集的大小,固定的开销逐渐变得不那么重要。

一件比较突出的事是,reduce()方法表现地比其他方法差。我的猜测是,设置函数调用(为了内联函数和脚本之间的转换)开销是很大的,并且JavaScript引擎实现器没有花任何时间优化这种案例,因为reduce在实际代码中不常使用。

更新:我夸大了我构造一个好的故事叙述的天真。就像我书的序言中指出的那样,我的故事也许并不完全正确,但他们已经足够真实。我当然知道JavaScript 如今是JITTED(即时解释执行),它改变了计算方式。(同时,是隐藏的数组副本。)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值