技术实践

Lodash在嵌套数组查找

Lodash在嵌套数组查找

羊先生的头像
羊先生2021.07.15 · 3 分钟阅读 · 84 阅读
Lodash在嵌套数组查找封面
文章正文还需 3 分钟

列子一

我知道urlTag,并基于此,我需要获取嵌套在nested数组内的标题。

js 复制代码
 myArray = [{
        "urlTag": "Google",
        "urlTitle": "Users",
        "status": 6,
        "nested": {
            "id": 2,
            "title": "http:\/\/www.google.com",
        }
    },
    {
        "urlTag": "Bing",
        "tabTitle": "BingUsers"
    }]

解决

result()或get()都能完成任务

唯一的区别是result()解析为函数时将调用路径:

js 复制代码
_.get(_.find(myArray, { urlTag: myUrl }), 'nested.title');
// → "http://www.google.com"

_.result(_.find(myArray, { urlTag: myUrl }), 'nested.title');
// → "http://www.google.com"

深层查找

isUndefined

检查 value 是否是 undefined

如果 value 是 undefined ,那么返回 true,否则返回 false

js 复制代码
const findCategoryById = (sections, id) => {
  var category;
  _.forEach(sections, (section) => {
    category = _.find(section.Categories, ['Id', id]);
    return _.isUndefined(category);
  });
  return category;
};


const ex = {
  "Sections": [{
    "Categories": [{
        "Name": "Book",
        "Id": 1,
        "Options": [{
          "Name": "AAAA",
          "OptionId": 111
        }],
        "Selected": 0
      },
      {
        "Name": "Car",
        "Id": 2,
        "Options": [{
          "Name": "BBB",
          "OptionId": 222
        }],
        "Selected": 0
      }
    ],
    "SectionName": "Main"
  }]
};

console.log(findCategoryById(ex.Sections, 2));

补充

findIndex

findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1

js 复制代码
const array1 = [5, 12, 8, 130, 44];

const isLargeNumber = (element) => element > 13;

console.log(array1.findIndex(isLargeNumber));
// expected output: 3

// 源码实现
Array.prototype.newFindIndex = function(callback) {
  const _arr = this;
  const len = _arr.length;
  for (let i = 0; i < len; i++) {
    if (callback(_arr[i], i, _arr)) {
      return i;
    }
  }
  return -1;
};

const array1 = [5, 12, 8, 130, 44];
const isLargeNumber = (element) => element > 13;
console.log(array1.newFindIndex(isLargeNumber));
// 3

findLastIndex

同样当我们倒叙查找首个满足条件的方法时,可以这样写:

js 复制代码
Array.prototype.newFindlastIndex = function(callback) {
  const _arr = this;
  const len = _arr.length;
  for (let i = len - 1; i >= 0; i--) {
    if (callback(_arr[i], i, _arr)) {
      return i;
    }
  }
  return -1;
};

const array1 = [5, 12, 8, 130, 44];
const isLargeNumber = (element) => element > 13;
console.log(array1.newFindlastIndex(isLargeNumber));
// 4

合并 findIndex 和 findLastIndex

大家可以看到,除了循环的条件不同,两个方法几乎一模一样,参考 lodash,我们将两个方法精简一下

js 复制代码
/**
 * @private
 * @param {Array} array The array to inspect.
 * @param {Function} predicate The function invoked per iteration.
 * @param {boolean} [fromRight] 从右向左查找
 * @returns {number} 返回第一个符合条件元素的下标或-1
 */
function baseFindIndex(array, predicate, fromRight) {
  const { length } = array;
  let index = fromRight ? length : -1; // 确定下标的边界

  while (fromRight ? index-- : ++index < length) {
    // index-- 用于倒序边界
    // ++index 用于正序的边界
    if (predicate(array[index], index, array)) {
      return index;
    }
  }
  return -1;
}

再来看看它的兄弟——underscore 的思路就是利用传参的不同,返回不同的函数。

js 复制代码
function createIndexFinder(dir) {
  return function(array, predicate, context) {
    const { length } = array;
    var index = dir > 0 ? 0 : length - 1;

    for (; index >= 0 && index < length; index += dir) {
      if (predicate.call(context, array[index], index, array)) return index;
    }
    return -1;
  };
}

var findIndex = createIndexFinder(1);
var findLastIndex = createIndexFinder(-1);

以上参考来自
https://www.thinbug.com/q/49190451
https://www.coder.work/article/2706443
https://blog.csdn.net/jbj6568839z/article/details/109646551