小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前言
这是一个朋友在面试过程中遇到的一道题目,具体是哪家公司,这里就不在说了,今天就展开分析一下这个题目,希望可帮到看到这个题目的朋友。
题目
实现 getValue 函数来获取对象 path 对应的值。
var object = { 'a': [{ 'b': { 'c': 3 } }] };
var array = [{ "a": { b: [1] } }];
getValue(object, 'a[0].b.c') // 输出 3
getValue(array, '[0].a.b[0]') // 输出 z
题目分析
获取对象或者数组的值,是通过对应的 key 或者 [index]。如果拿到完整的 path 要获得对应的值,就需要先去分解 path,然后一层层的去取值。
如果没有找到对应的 path,则返回默认值
将 path 进行分解
path.split(".");
对 path 进行分类,可分为三种请情况
- 对象的
key:'a'、'aaa' - 数组的
index:'[0]' '[2]' - 对象
key + index:aa:[0]
根据每一层的 path 获取对应的值
完整代码
function getValue(obj, path = "") {
const paths = path.split(".");
const attr = paths.shift();
let result = "";
// 正则表达式,用于匹配三种不同情况和分组取值
// 'a'、'aaa'
const reg1 = /^([a-zA-Z]+)$/;
// '[0]' '[2]'
const reg2 = /^(\[\d+\])$/;
// aa:[0]
const reg3 = /^([a-zA-Z]+)(\[\d+\])$/;
// 根据每一层的 `path` 获取对应的值
const _getValue = (paths, val) => {
if (paths.length > 0 && (val !== null || val !== undefined)) {
// 根据剩余的 path 继续执行查找
result = getValue(val, paths.join("."));
}
};
if (reg1.test(attr)) {
// 获取第一层的值
let val = obj[attr];
result = val;
// 继续执行深层次的查找
_getValue(paths, val);
} else if (reg2.test(attr)) {
const index = attr.substr(1, attr.length - 2);
let val = obj[index];
result = val;
// 继续执行深层次的查找
_getValue(paths, val);
} else if (reg3.test(attr)) {
const { $1, $2 } = RegExp;
let parentVal = obj[$1];
const index = $2.substr(1, $2.length - 2);
let val = parentVal[index];
result = val;
// 继续执行深层次的查找
_getValue(paths, val);
}
return result;
};
console.log(getValue(object, 'a[0].b.c')) // 3
console.log(getValue(array, '[0].a.b[0]')) // 1
附:
【 lodash.get 】
解题2
function getValue(obj, path) {
const keys = path
.replace(/\[(\d+)\]/g, '.$1') // 将 [index] 转换为 .index
.split('.')
.filter(Boolean); // 将路径字符串分割成键的数组
console.log('keys: ', keys)
let value = obj;
for (const key of keys) {
if (value && typeof value === 'object' && key in value) {
value = value[key];
} else {
return undefined; // 如果未找到路径中的某个键,则返回 undefined
}
}
return value;
}
结语
如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。
文章如有错误之处,希望在评论区指正🙏🙏。