lodash源码分析每日一练 - 数组 - findIndex / findLastIndex

今日分享:

每一步都是曼妙的风景~

__.findIndex(array, [predicate=_.identity], [fromIndex=0])

使用:
遍历数组元素,返回第一个通过 predicate 判断为真值的元素的索引值(index)。
使用示例:

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

尝试手写:

①返回索引值;②返回第一个符合条件的索引值;③可以指定从哪个位置开始查询

	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
    // ……

源码方案:

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

使用:
使用示例

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

源码方案:

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个值开始查询,并不支持从后往前查询。

你可能感兴趣的:(lodash每日一源,前端,javascript)