// Generator function to create the findIndex and findLastIndex functions.
var createPredicateIndexFinder = function(dir) {
return function(array, predicate, context) {
predicate = cb(predicate, context);
var length = getLength(array);
var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
return -1;
};
};
// Returns the first index on an array-like that passes a predicate test.
_.findIndex = createPredicateIndexFinder(1);
_.findLastIndex = createPredicateIndexFinder(-1);
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iteratee, context) {
iteratee = cb(iteratee, context, 1);
var value = iteratee(obj);
var low = 0, high = getLength(array);
while (low < high) {
var mid = Math.floor((low + high) / 2);
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
}
return low;
}; // 二分搜索法
// Generator function to create the indexOf and lastIndexOf functions.
var createIndexFinder = function(dir, predicateFind, sortedIndex) {
return function(array, item, idx) {
var i = 0, length = getLength(array);
if (typeof idx == 'number') {
if (dir > 0) {
i = idx >= 0 ? idx : Math.max(idx + length, i);
} else {
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
}
} else if (sortedIndex && idx && length) {
idx = sortedIndex(array, item);
return array[idx] === item ? idx : -1;
}
if (item !== item) {
idx = predicateFind(slice.call(array, i, length), _.isNaN);
return idx >= 0 ? idx + i : -1;
}
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
if (array[idx] === item) return idx;
}
return -1;
};
};
// Return the position of the first occurrence of an item in an array,
// or -1 if the item is not included in the array.
// If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search.
_.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
_.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
// Generate an integer Array containing an arithmetic progression. A port of
// the native Python `range()` function. See
// [the Python documentation](http://docs.python.org/library/functions.html#range).
_.range = function(start, stop, step) {
if (stop == null) {
stop = start || 0;
start = 0;
}
if (!step) {
step = stop < start ? -1 : 1;
}
var length = Math.max(Math.ceil((stop - start) / step), 0);
var range = Array(length);
for (var idx = 0; idx < length; idx++, start += step) {
range[idx] = start;
}
return range;
};
// Split an **array** into several arrays containing **count** or less elements
// of initial array.
_.chunk = function(array, count) {
if (count == null || count < 1) return [];
var result = [];
var i = 0, length = array.length;
while (i < length) {
result.push(slice.call(array, i, i += count));
}
return result;
};
今天看来有不少之前看过,而且要回顾的东西。。。。
createPredicateIndexFinder
// Generator function to create the findIndex and findLastIndex functions.
var createPredicateIndexFinder = function(dir) {
return function(array, predicate, context) {
predicate = cb(predicate, context);
var length = getLength(array);
var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
return -1;
};
};
之前我们只是简略分析过这个函数,现在我们具体划分
一开始的结构:
var createPredicateIndexFinder = function (dir) {
return function (array, predicate, context) {
}
} // 构造函数
之后在return 的function内部:
// 传入参数:array, predicate, context
predicate = cb(predicate, context)
var length = getLength(array);
var index = dir > 0 ? 0: length - 1; // 按照dir的正负定义开头在哪里
变量定义完成,接下来就该for循环遍历了
for (; index >= 0 && index < length; index+=dir) {
} //+=dir说明dir的大小决定遍历的方式
接下来截取
for (; index >= 0 && index < length; index+=dir) {
if (predicate(array[index], index, arrray)) return index // 找到则立刻返回真值的index
}
return -1; // 找不到则默认返回 -1
一个createPredicateIndexFinder就这样完成了
过渡部分
_.findIndex = createPredicateIndexFinder(1); // findIndex从开头一个个找
_.findLastIndex = createPredicateIndexFinder(-1); // lastIndex从结尾一个个找
_.sortedIndex
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iteratee, context) {
iteratee = cb(iteratee, context, 1);
var value = iteratee(obj);
var low = 0, high = getLength(array);
while (low < high) {
var mid = Math.floor((low + high) / 2);
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
}
return low;
};
还是那句话
还是拆开分析
_.sortedIndex = function (array, obj, iteratee, context) {
}
没问题,传入四个参数array, obj, iteratee, context
看函数内部:
iteratee = cb(iteratee, context, 1); // 说明iteratee仅传入一个参数
var value = iteratee(obj); // 值的对比
var low = 0, high = getLength(array)) //定义最大值与最小值
while (low < high) {
var mid = Math.floor((low + high)/2);
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid
} //二分搜索
return low
createIndexFinder
// Generator function to create the indexOf and lastIndexOf functions.
var createIndexFinder = function(dir, predicateFind, sortedIndex) {
return function(array, item, idx) {
var i = 0, length = getLength(array);
if (typeof idx == 'number') {
if (dir > 0) {
i = idx >= 0 ? idx : Math.max(idx + length, i);
} else {
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
}
} else if (sortedIndex && idx && length) {
idx = sortedIndex(array, item);
return array[idx] === item ? idx : -1;
}
if (item !== item) {
idx = predicateFind(slice.call(array, i, length), _.isNaN);
return idx >= 0 ? idx + i : -1;
}
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
if (array[idx] === item) return idx;
}
return -1;
};
};
结构依然同createPredicateIndexFinder一样
var createIndexFinder = function (dir, predicateFind, sortedIndex) {
return function (array, item, idx) {
}
}
传入三个参数array, item, index
生成的函数内部
var i = 0, length = getLength(array);
if (typeof idx == 'number') {
if (dir > 0) {
} else {
}
} else if (sortedIndex && idx && length) {
idx = sortedIndex(array, item);
return array[idx] === item ? idx : -1;
} //如果idx没有或者为0,且有sortedindex加入,则用二分法
if (typeof idx == 'number') {
if (dir > 0) {
i = idx >= 0 ? idx : Math.max(idx + length, i); // 当有index时,index>0, 则取index值
} else {
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
}
} else if (sortedIndex && idx && length) {
}
之后有
if (item !== item) {
idx = predicateFind(slice.call(array, i, length), _.isNaN);
return idx >= 0 ? idx + i : -1;
} // 若item = NaN什么的,则单独处理该情况
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
if (array[idx] === item) return idx;
}
return -1; // 剩余情况
.indexof, .lastIndexOf
// Return the position of the first occurrence of an item in an array,
// or -1 if the item is not included in the array.
// If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search.
_.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
_.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
_.range
// Generate an integer Array containing an arithmetic progression. A port of
// the native Python `range()` function. See
// [the Python documentation](http://docs.python.org/library/functions.html#range).
_.range = function(start, stop, step) {
if (stop == null) {
stop = start || 0; //如果不设定stop,那就变为start, 即stop变量提前
start = 0; //start则变为0
}
if (!step) {
step = stop < start ? -1 : 1;
// 没有step的时候,则step默认为1,否则如果stop为负,则step为-1
}
var length = Math.max(Math.ceil((stop - start) / step), 0);
var range = Array(length);
for (var idx = 0; idx < length; idx++, start += step) {
range[idx] = start;
}
return range; //返回range
};
_.chunk
// Split an **array** into several arrays containing **count** or less elements
// of initial array.
_.chunk = function(array, count) {
if (count == null || count < 1) return [];
var result = [];
var i = 0, length = array.length;
while (i < length) {
result.push(slice.call(array, i, i += count));
}
return result;
};
这个方法就连官方文档上都没有记录,效果注释上已经解释,分开看
_.chunk = function(array, count) {
if (count == null || count < 1) return [];
// 仅传入数组时或者count < 1时,永远返回一个空数组
var result = [];
var i = 0, length = array.length;
while (i < length) {
result.push(slice.call(array, i, i += count));
}
return result;
};
该方法也可对字符串使用,用于按数量分割字符串,并入一个数组中,可与_.difference合用。
没了