zoukankan      html  css  js  c++  java
  • JS 两个数组合并

    让我们先考虑下面这情况:

    代码如下:

    var a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
    var b = [ "foo", "bar", "baz", "bam", "bun", "fun" ];


    很显然最简单的结合结果应该是:

    代码如下:

    [
    1, 2, 3, 4, 5, 6, 7, 8, 9,
    "foo", "bar", "baz", "bam" "bun", "fun"
    ]

    concat(..)

    这是最常见的做法:

    代码如下:

    var c = a.concat( b );
    a; // [1,2,3,4,5,6,7,8,9]
    b; // ["foo","bar","baz","bam","bun","fun"]
    c; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]

    正如你所看到的,C是一个全新的数组,表示a和b两个数组的组合,并让A和B不变。简单吧?

    但如果a有10,000个元素,而b也有一万个元素? C就会有2万个元素,所以a和b的内内存使用就会翻倍。

    “没问题!”,你说。让它们被垃圾回收,把A和B设置为null,问题解决了!

    a = b = null; // 'a'和'b'就被回收了

    呵呵。对于只有几个元素的小数组,这没啥问题。但对于大数组,或者在内存有限的系统中需要经常重复这个过程,它其实还有很多改进的地方。 
    循环插入

    好吧,让我们将一个数组的内容复制到另一个,使用: Array#push(..)

    代码如下:

    // `b` onto `a`
    for (var i=0; i < b.length; i++) {
    a.push( b[i] );
    }
    a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
    b = null;

    现在,数组a有了数组b的内容。

    似乎有更好的内存占用。

    但如果a数组比较小?出于内存和速度的原因,你可能要把更小的a放到b的前面,。没问题,只需将push(..)换成unshift(..)即可:

    代码如下:

    // `a` into `b`:
    for (var i=a.length-1; i >= 0; i--) {
    b.unshift( a[i] );
    }
    b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]


    功能技巧

    不过for循环确实比较丑,而且不好维护。我们可以做的更好吗?

    这是我们的第一次尝试,使用Array#reduce:

    代码如下:

    // `b` onto `a`:
    a = b.reduce( function(coll,item){
    coll.push( item );
    return coll;
    }, a );

    a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]

    // or `a` into `b`:
    b = a.reduceRight( function(coll,item){
    coll.unshift( item );
    return coll;
    }, b );

    b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]


    Array#reduce(..) 和 Array#reduceRight(..)是不错的,但他们是一点点笨拙。 ES6=>的箭头函数将减少一些代码量,但它仍然需要一个函数,每个元素都需要调用一次,不是很完美。

    那这个怎么样:

    代码如下:

    // `b` onto `a`:

    a.push.apply( a, b );

    a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]

    // or `a` into `b`:

    b.unshift.apply( b, a );

    b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]


    这是一个要好很多吧?特别是因为 unshift(..)方法在这里并不需要担心前面的反向排序。 ES6的spead操作会更漂亮: a.push( ...b ) 或 b.unshift( ...a

    数组最大长度限制

    第一个主要的问题是,内存使用量增长了一倍(当然只是暂时的!)被追加内容基本上是通过函数调用将元素复制到堆栈中。此外,不同的JS引擎都有拷贝数据长度的限制。

    所以,如果数组有一百万个元素,你肯定会超出了push(...)或unshift(...)允许调用堆栈的限制。唉,处理几千个元素它会做得很好,但你必须要小心,不能超过合理的长度限值。

    注意: 你可以尝试一下splice(...),它跟push(...)和unshift(...)一样都有这种问题。

    有一种方法可以避免这种最大长度限制。

    代码如下:

    function combineInto(a,b) {
    var len = a.length;
    for (var i=0; i < len; i=i+5000) {
    b.unshift.apply( b, a.slice( i, i+5000 ) );
    }
    }

    等一下,我们的可读性倒退了。 就这样吧,可能会越改越差,呵。

  • 相关阅读:
    Composite in Javascript
    Model Validation in Asp.net MVC
    HttpRuntime.Cache vs. HttpContext.Current.Cache
    Controller Extensibility in ASP.NET MVC
    The Decorator Pattern in Javascript
    The Flyweight Pattern in Javascript
    Model Binding in ASP.NET MVC
    Asp.net MVC
    jQuery Ajax 实例 全解析
    ASP.NET AJAX入门系列
  • 原文地址:https://www.cnblogs.com/lbonet/p/6991636.html
Copyright © 2011-2022 走看看