js数组应用

判断数组

在js中怎么判断一个数组,使用instanceof就能轻易解决这个问题,可以参考另一篇博文typeof和instanceof详解

   [] instanceof Array  // true

instanceof的操作符问题在于,它假定只有一个全局执行环境,如果网页中包含多个框架,也就是存在两个以上不同的全局执行环境,就存在两个以上不同版本的Array构造函数。如果你从一个框架向另一个框架传入一个数组,那么传入的数组与第二个框架中原生创建的数组分别具有不同的构造函数
为了解决这个问题,ECMAScript5新增了Array.isArray()方法

   if(Array.isArray(value)){
       // 如果value是数组
   }

isArray的实现大概是这样的:

    function isArray(o) {
        // 利用参数的toString方法
        return Object.prototype.toString.call(o) === '[object Array]';
    }
    Array.prototype.isArray = isArray;

具体应用

有这样一个问题,数组A和数组B有序(暂定从小到大),如何判断B是不是数组A的子集
如果忽略有序这个条件,我们很容易想到这样一种实现方式

  var arrA, 
      arrB;    //省略初始化
  function isSubCollection(arrA, arrB){
      var arrC = arrA.concat();  // 用数组C深拷贝数组A,避免破坏arrA
      for(var i = 0, len = arrB.length; i < len; i++){
          //在数组C中,返回数组B元素的索引
          var index = arrC.indexOf(arrB[i]);
          if(index >= 0){
              //将数组C中与B相同的元素切掉一个
              arrC.splice(index, 1);
          } else {
              return false;
          }
      }
      return true;
  }

上面这个方法明显没有用到有序这个条件,导致每次indexOf实际上重复遍历数组A,那么接下来我们使用另一种方法

   var arrA, 
      arrB;    //省略初始化
   function isSubCollection(arrA, arrB){
       var pos = 0;
       var isFind = false;
       for(var i = 0, len = arrB.length; i < len; i++){
           isDiff = false;
           //使用循环判断arrB中的元素是否在arrA中,并且用一个pos变量记录在arrA的游标,减少循环次数
           for(var j = pos, _len = arrA.length; j< _len; j++){
              if(arrA[j] == arrB[i]){
                 pos = j;
                 isFind = true;
              } 
           }
           if(!isFind) return false;
       }
       return true;
     }

看起来效率高了一些,但实际上没高多少。说到有序,我们自然会想到二分查找,如果两个同时都是大数组,那么使用二分查找来判断数组A中是否有数组B的元素显然更快,时间复杂度为logN

    var arrA, 
          arrB;    //省略初始化
    function isSubCollection(arrA, arrB){
       for(var i = 0, len = arrB.length; i < len; i++){
           if(!isFind(arrA, arrB[i])) return false;
       }
       return true;
     }
     //使用二分查找
     function isFind(arr, target){
        var upper = arr.length - 1;
        var lower = 0;
        while(lower <= upper){
            var mid = Math.floor((upper + lower) / 2);

            if(arr[mid] == target){
               return true;
            } else if(arr[mid] < target){
               lower = mid + 1;
            } else {
               upper = mid - 1;
            }
        }
        return false;
     }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值