underscore中indexof实现

index里面有一个有趣的点:

查找值NaN的情形

	//_.findIndex  特殊情况下的处理方案  NAN  
	//_.sortedIndex 针对排序的数组做二分查找  优化性能
	_.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
    _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);


	function createIndexFinder(dir, predicateFind, sortedIndex) {

		return function(array, item, idx) {//console.log(_.indexOf([1,2,NaN, 4,5,6],NaN,true));
			
			var i = 0,
			length = array.length;

			//先判断被查找的值是不是NaN,如果要查找的元素是 NaN 类型  NaN !== NaN
			if (item !== item) {
				console.log([].slice.call(array, i, length))
               
				idx = predicateFind([].slice.call(array, i, length), _.isNaN);
//_.findIndex
				return idx >= 0 ? idx + i : -1;
			}

      // 第三个参数true用二分查找优化   _.isBoolean(idx)为true代表idx是布尔值;idx为true代表排过序的; 否则 遍历查找
      //如果先判断第三个参数true的话,被查找的是NaN的话,就会在下面这个if语句中输出-1;不会进入if (item !== item) {}里面;所以NaN值的判断应该放在前面;    
			if (sortedIndex && _.isBoolean(idx) && idx && length) {
				
				// 能用二分查找加速的条件
				// 用 _.sortedIndex 找到有序数组中 item 
				idx = sortedIndex(array, item);
				
				return array[idx] === item ? idx : -1; 
                               //有可能是idx,有可能是-1;
			}
			


			// 非上述情况正常遍历
			for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
				if (array[idx] === item) return idx;
			}

			return -1;
		};
	}

二分法查找函数: sortedIndex

	_.sortedIndex = function(array, obj, iteratee, context) {
		// 重点:cb函数 if (iteratee == null) {return function(value){return value;}}这里很妙!
		iteratee = cb(iteratee, context, 1);
		var value = iteratee(obj);
		var low = 0,
			high = array.length;
		// 二分查找
		while (low < high) {  //4  4 
			var mid = Math.floor((low + high) / 2);   //4
			
			if (iteratee(array[mid]) < value)    //  5 < 5
				low = mid + 1;  //4 如果找不到就 low = mid + 1,
			else
				high = mid;   //4  中间值赋值给high;
		}
        
		return low;     //4  sortedIndex 一定会返回一个值;但是这个值不一定就是===value;
	};

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值