这是之前字节面试时的一道题,当时脑子比较混乱,但在面试官指引下还是写出了大部分,后面又仔细想了想,感觉还是得多写题。我们来看看吧
题目
const entry = [{
id: '1',
isOpen: true
}, {
id: '2',
children: [{
id: '21',
children: [{
id: '211',
isOpen: false
}, {
id: '212',
isOpen: false
}]
}]
}, {
id: '3',
isOpen: false
}]
// 平铺,如果有isOpen属性则直接输出,如果没有则查看children里面有没有
// 只要children里面有一个true,那么外层就是true
let output = {'1':true, '2':true, '21':true, '211':true, '212':false, '3':false}
思路:
(1)首先是先遍历这个树状数组的每一层,拿到 id 当 key,如果有 isOpen 属性,则直接把 isOpen 属性赋给 key,如果没有 则先 递归得到 children的遍历结果,并用 Object.assign合并res和递归的结果
没有isOpen属性的则被跳过了,因此我们把没有isOpen属性的单独考虑
(2)做到这里,有 isOpen 属性已经得到了 ,但是没有 isOpen 属性的我们则需要另外考虑,我的思路就是另外写一个judge函数来递归判断 其 children 内有没有 isOpen 是 等于 true的
function flatObj(arr) {
let res = {}
for (const item of arr) {
let id = item.id
let isOpen = item.isOpen
if (isOpen !== undefined) {
res[id] = isOpen
} else {
// 没有isOpen则查找children,并且合并递归结果
Object.assign(res, flatObj(item.children))
// 没有isOpen单独考虑
res[id] = judge(item.children)
}
// 分步打印看结果
console.log(res);
}
return res
}
// 判断children内是否有isOpen=true
function judge(arr){
let flag = false
for (const item of arr) {
let isOpen = item.isOpen
if (isOpen !== undefined) {
if(isOpen){
flag = true
}
} else {
// 如果还是没有,则继续去children内找,最后都没有则返回false
flag = judge(item.children)
}
}
return flag
}
console.log(flatObj(entry));
最后我们来看指向结果,由于直接看结果不明显,因此我们把它分步打印出来
由结果我们可以看出,3是被最后才加进去的,由于对象内部的key排列问题,3被排到了前面,但这不影响结果。