今日分享:
每一步都是曼妙的风景~
__.findIndex(array, [predicate=_.identity], [fromIndex=0])
使用:
遍历数组元素,返回第一个通过 predicate 判断为真值的元素的索引值(index)。
使用示例:
js
var users = [
{ 'user': 'barney', 'active': false },
{ 'user': 'fred', 'active': false },
{ 'user': 'pebbles', 'active': true }
];
_.findIndex(users, function(o) { return o.user == 'barney'; });
// => 0
// The `_.matches` iteratee shorthand.
_.findIndex(users, { 'user': 'fred', 'active': false });
// => 1
// The `_.matchesProperty` iteratee shorthand.
_.findIndex(users, ['active', false]);
// => 0
// The `_.property` iteratee shorthand.
_.findIndex(users, 'active');
// => 2
尝试手写:
①返回索引值;②返回第一个符合条件的索引值;③可以指定从哪个位置开始查询
js
let find_users = [
{ 'user': 'barney', 'active': false },
{ 'user': 'fred', 'active': false },
{ 'user': 'pebbles', 'active': true }
];
function my_findIndex (arr, predicate, start = 0){
start = start >=0 && start < arr.length ? start : 0;
if(arr.length === 0) { return -1 }
if( predicate instanceof Array ) {
let i = start;
while (i < arr.length) {
if(arr[i][predicate[0]] === predicate[1]) {
return i;
}
i++;
}
} else if( predicate instanceof Object) {
let i = start;
while (i < arr.length) {
let flag = true;
for (let key in predicate) {
if(arr[i][key] != predicate[key]) {
flag = false
}
}
if(flag) return i;
i++;
}
} else if(predicate instanceof Function) {
for(let i = start; i < arr.length; i++) {
if(predicate(arr[i]) ) return i;
}
} else {
let i = start;
while (i < arr.length) {
console.log(arr[i][predicate])
if(arr[i][predicate] == true) {
return i;
}
i++;
}
}
return -1;
}
console.log(my_findIndex(find_users, 'active')) // 2
// ......
源码方案:
js
function findIndex(array, predicate, fromIndex) {
var length = array == null ? 0 : array.length;
if (!length) {
return -1;
}
var index = fromIndex == null ? 0 : toInteger(fromIndex);
if (index < 0) {
index = nativeMax(length + index, 0);
}
return baseFindIndex(array, baseIteratee(predicate, 3), index);
}
// 关键逻辑一:
// 除了常规的对array参数的排除异常值,需要对第二个参数进行类型判断,然后分别进行处理
// 大致需要处理 object array function 及字符串类型
function baseIteratee(value) { if (typeof value == 'function') {
return value;
}
if (value == null) {
return identity;
}
if (typeof value == 'object') {
return isArray(value)
? baseMatchesProperty(value[0], value[1])
: baseMatches(value);
}
return property(value);
}
// 关键逻辑二:
// 关键值为对象时的处理
function baseIsMatch(object, source, matchData, customizer) {
var index = matchData.length,
length = index,
noCustomizer = !customizer;
if (object == null) {
return !length;
}
object = Object(object);
while (index--) {
var data = matchData[index];
if ((noCustomizer && data[2])
? data[1] !== object[data[0]]
: !(data[0] in object)
) {
return false;
}
}
while (++index < length) {
data = matchData[index];
var key = data[0],
objValue = object[key],
srcValue = data[1];
if (noCustomizer && data[2]) {
if (objValue === undefined && !(key in object)) {
return false;
}
} else {
var stack = new Stack;
if (customizer) {
var result = customizer(objValue, srcValue, key, object, source, stack);
}
if (!(result === undefined
? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
: result
)) {
return false;
}
}
}
return true;
}
// 关键逻辑三:
// 关键值类型为函数时的处理
function baseFindIndex(array, predicate, fromIndex, fromRight) {
var length = array.length,
index = fromIndex + (fromRight ? 1 : -1);
while ((fromRight ? index-- : ++index < length)) {
if (predicate(array[index], index, array)) {
return index;
}
}
return -1;
}
// 关键逻辑四:
// 关键值为数组时的处理逻辑
function baseMatchesProperty(path, srcValue) {
if (isKey(path) && isStrictComparable(srcValue)) {
return matchesStrictComparable(toKey(path), srcValue);
}
return function(object) {
var objValue = get(object, path);
return (objValue === undefined && objValue === srcValue)
? hasIn(object, path)
: baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
};
}
// 关键值为其他基础类型时的处理
function property(path) {
return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
}
function basePropertyDeep(path) {
return function(object) {
return baseGet(object, path);
};
}
function baseGet(object, path) {
path = castPath(path, object);
var index = 0,
length = path.length;
while (object != null && index < length) {
object = object[toKey(path[index++])];
}
return (index && index == length) ? object : undefined;
}
类似方法
_.findLastIndex
使用:
使用示例
js
var users = [
{ 'user': 'barney', 'active': true },
{ 'user': 'fred', 'active': false },
{ 'user': 'pebbles', 'active': false }
];
_.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
// => 2
// The `_.matches` iteratee shorthand.
_.findLastIndex(users, { 'user': 'barney', 'active': true });
// => 0
// The `_.matchesProperty` iteratee shorthand.
_.findLastIndex(users, ['active', false]);
// => 2
// The `_.property` iteratee shorthand.
_.findLastIndex(users, 'active');
// => 0
源码方案:
js
function findLastIndex(array, predicate, fromIndex) {
var length = array == null ? 0 : array.length;
if (!length) {
return -1;
}
var index = length - 1;
if (fromIndex !== undefined) {
index = toInteger(fromIndex);
index = fromIndex < 0
? nativeMax(length + index, 0)
: nativeMin(index, length - 1);
}
return baseFindIndex(array, baseIteratee(predicate, 3), index, true);
}
方案对比
自己手写的部分只考虑到从第n个值开始查询,并不支持从后往前查询。