【问题标题】:Is Splice faster than Shift + Pop? Why?Splice 比 Shift + Pop 快吗?为什么?
【发布时间】:2013-02-09 18:13:16
【问题描述】:

我从一些非特定来源获悉,使用shift()pop() 的组合比使用splice() 更快。我还没有运行基准测试,而且很可能有一段时间不会运行,因为我不在城里,但这是真的吗?如果是,为什么?

【问题讨论】:

  • 或许你可以推荐给jacksondunstan.com
  • +1 建议使用 ActionScript 基准测试向导 :) 他的网站上有很多很棒的技巧。

标签: actionscript-3


【解决方案1】:

如果您不需要保留数组的顺序,使用.pop().splice() 快得多。

.splice() 将删除给定索引处的元素。然后发生的情况是,数组中的每个其他元素都需要将其在数组中的位置减少 1。如果您的数组很大并且删除元素的索引很小,这可能会很慢。

使用.pop(),您可以完全删除重新索引所有内容的过程。您可以使用.pop() 从数组中删除最后一项,而不是删除给定索引处的元素。从这里,您需要做的就是将您要删除的项目替换为您使用.pop() 获得的项目。如前所述,这当然意味着元素的顺序不会得到维护。

代码示例:

.splice():

var list:Array = [0,1,2,3,4,5];
list.splice(2, 1);

trace(list); // 0,1,3,4,5

然后.pop():

var last:* = list.pop();
list[2] = last;

trace(list); // 0,1,5,4 - Notice we move 5 to the index 2 and lose the order.

这里有最重要的实际性能测试:

var list:Array = [];
function fillList():void
{
    for(var i = 0; i < 200000; i++) list.push(i);
}


function emptyViaSplice():void
{
    fillList();
    var t:Number = getTimer();

    while(list.length > 0)
    {
        list.splice(0, 1);
    }

    trace("emptyViaSplice: " + (getTimer() - t));
}


function emptyViaPop():void
{
    fillList();
    var t:Number = getTimer();

    while(list.length > 0)
    {
        if(list.length == 1) list.pop();
        else
        {
            var l:* = list.pop();
            list[0] = l;
        }
    }

    trace("emptyViaPop: " + (getTimer() - t));
}

结果:

emptyViaSplice(); // 12153 ms
emptyViaPop(); // 37 ms

【讨论】:

    【解决方案2】:

    我尝试了另一个代码,结果如下所示:

    var length = 200000;
    function fillList() {
        var list = [];
        for(var i = 0; i < length; i++)
            list.push(i);
        return list;
    }
    
    function halfViaSplice() {
      var list = fillList();
      var startTime = new Date();
      list.splice(length/2, length/2);
      var endTime = new Date();
    
      console.log("halfViaSplice: " + (endTime - startTime));
    }
    
    function halfViaPop() {
      var list = fillList();
      var startTime = new Date();
    
      while(list.length > length/2) {
        list.pop();
      }
      var endTime = new Date();
    
      console.log("halfViaPop: " + (endTime - startTime));
    }
    
    halfViaSplice();
    halfViaPop();
    

    结果:

    halfViaSplice: 0
    halfViaPop: 4
    

    我同意 Marty 的回答,但如果您从一个索引中删除所有最后一个数据,而不是仅删除孔位置,我会建议拼接而不是弹出。

    【讨论】:

      【解决方案3】:

      经典算法有时更快。不更改数组大小是实现非常快速性能的另一种方法。 在使用 performance.now() 进行了几次测试之后,我发现在下面的案例中,这个经典算法比任何改变数组大小的方法都快,并且像所有 javascript 代码一样,使用本地变量变得更快。

      var ArrayLength = Array.length; // always prefer the simplest references.
      for (i=1; i < ArrayLength; i++) {Array[(i-1)] = Array[i];}  
      Array [ArrayLength-1] = [[newdata1],[newdata2]];
      

      在同等情况下比较,上面的代码被证明比

      Array.shift(); Array.push([[newdata1],[ newdata2]]);
      

      对于周期性变化的小数组(20到60个索引),你绝对应该考虑经典算法。

      【讨论】:

        猜你喜欢
        • 2011-09-23
        • 1970-01-01
        • 1970-01-01
        • 2019-11-02
        • 1970-01-01
        • 1970-01-01
        • 2015-07-24
        相关资源
        最近更新 更多