问题1:在嵌套对象中查找并打印年龄大于30的用户姓名
JavaScript文件:
const users = {
user1: {
name: "Alice",
age: 25,
details: {
city: "New York",
occupation: "Engineer"
}
},
user2: {
name: "Bob",
age: 35,
details: {
city: "Los Angeles",
occupation: "Designer"
}
},
user3: {
name: "Charlie",
age: 28,
details: {
city: "Chicago",
occupation: "Manager"
}
},
user4: {
name: "David",
age: 42,
details: {
city: "Houston",
occupation: "Developer"
}
}
};
// 解决方案
function findUsersOver30(obj) {
const result = [];
for (const key in obj) {
if (obj[key].age > 30) {
result.push(obj[key].name);
}
}
return result;
}
const usersOver30 = findUsersOver30(users);
console.log(usersOver30); // 输出: ["Bob", "David"]
输出: ["Bob", "David"]
解释:
这个解决方案遍历嵌套对象,检查每个用户的年龄是否大于30,如果满足条件就将用户名添加到结果数组中。
问题2:扁平化数组(输入: [1,2,[3,4], 5], 输出: [1,2,3,4,5])
解决方案1:使用flat()方法
const arr = [1, 2, [3, 4], 5];
const flattenedArr = arr.flat();
console.log(flattenedArr); // 输出: [1, 2, 3, 4, 5]
但是这种方法不会扁平化多层嵌套。
解决方案2:使用flat()配合Infinity
const arr = [1, 2, [3, 4, [5, 6]], 7];
const flattenedArr = arr.flat(Infinity);
console.log(flattenedArr); // 输出: [1, 2, 3, 4, 5, 6, 7]
解决方案3:使用递归和for循环
function flattenArray(arr) {
let result = [];
arr.forEach(item => {
if (Array.isArray(item)) {
result = result.concat(flattenArray(item));
// ---------- 或者 ------
// result = [...result, ...flattenArray(item)];
} else {
result.push(item);
}
});
return result;
}
const arr = [1, 2, [3, 4, [5, 6]], 7];
const flattenedArr = flattenArray(arr);
console.log(flattenedArr); // 输出: [1, 2, 3, 4, 5, 6, 7]
解决方案4:使用递归和reduce方法
function flattenArray(arr) {
return arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? flattenArray(val) : val), []);
}
const arr = [1, 2, [3, 4, [5, 6]], 7];
const flattenedArr = flattenArray(arr);
console.log(flattenedArr); // 输出: [1, 2, 3, 4, 5, 6, 7]
解决方案对比分析
flat()方法
o 优点:简洁、内置方法
o 缺点:需要指定深度,多层嵌套需要Infinity
o 适用场景:简单的一层或已知深度的扁平化
递归方法
o 优点:可以处理任意深度的嵌套
o 缺点:代码相对复杂
o 适用场景:未知深度的复杂嵌套数组
reduce方法
o 优点:函数式编程风格,代码简洁
o 缺点:可能不如for循环直观
o 适用场景:偏好函数式编程的场景
性能考虑
1. flat()方法:现代浏览器中性能最好
2. 递归方法:对于深层嵌套可能产生栈溢出
3. 迭代方法:可以避免栈溢出,适合大数据集
实际应用场景
1. 数据处理:处理来自API的嵌套数据
2. 表单数据:扁平化表单字段
3. 配置对象:处理嵌套的配置结构
4. 树形结构:将树形数据转换为扁平列表
更多JavaScript棘手问题请访问:
o JavaScript棘手代码第一部分
o JavaScript棘手代码 - 处理设备方向
关键概念总结
1. 对象遍历:使用for...in循环遍历对象属性
2. 数组扁平化:多种方法处理嵌套数组
3. 递归编程:处理未知深度的数据结构
4. 函数式编程:使用reduce等函数式方法
5. 性能优化:选择合适的方法处理不同场景
扩展练习
练习1:深度扁平化对象
const deepObject = {
a: 1,
b: {
c: 2,
d: {
e: 3,
f: [4, 5, { g: 6 }]
}
}
};
// 将嵌套对象扁平化为单层对象
function flattenObject(obj, prefix = '') {
return Object.keys(obj).reduce((acc, key) => {
const pre = prefix.length ? prefix + '.' : '';
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
Object.assign(acc, flattenObject(obj[key], pre + key));
} else {
acc[pre + key] = obj[key];
}
return acc;
}, {});
}
console.log(flattenObject(deepObject));
// 输出: { a: 1, 'b.c': 2, 'b.d.e': 3, 'b.d.f': [4, 5, { g: 6 }] }
练习2:条件扁平化
function conditionalFlatten(arr, condition) {
return arr.reduce((acc, item) => {
if (Array.isArray(item) && condition(item)) {
return acc.concat(conditionalFlatten(item, condition));
} else if (Array.isArray(item)) {
return acc.concat(item);
} else {
return acc.concat(item);
}
}, []);
}
// 只扁平化包含数字的数组
const mixedArray = [1, [2, 3], ['a', 'b'], [4, [5, 6]]];
const result = conditionalFlatten(mixedArray, arr =>
arr.some(item => typeof item === 'number')
);
console.log(result);