一道前端算法题, 想了要好久没想出来如何写 . 请大神指导一下

2019-05-21 09:33:32 +08:00
 lyshine

题目是:

给一个数据结构如下
var data = [
{
    "name": "手机",
    "childs": [
        {
            "name": "iPhone",
            "childs": [
                {"name": "iPhone X"},
                {"name": "iPhone XR"},
                {"name": "iPhone XS"},
            ]
        },
        {
            "name": "HUAWEI",
            "childs": [
                {"name": "HUAWEI Mate 20"},
                {"name": "HUAWEI Mate 20 X"},
                {"name": "HUAWEI Mate 20 Pro"},
            ]
        }
    ]
}

];

然后让封装一个函数, 根据名称得到其遍历的路径. 例如参数是  HUAWEI Mate 20. 那么函数返回 手机 / HUAWEI/HUAWEI Mate 20.  要求函数可以适用多层的数据结构, 例如上面的数据只有三层深度, 如果扩展为 10 层的话函数仍然可以适用. 

这个题目的其实就是一个树的遍历, 然后返回这个遍历路径. 但是想了半天没想到如何写
5546 次点击
所在节点    编程
30 条回复
poisedflw
2019-05-21 15:26:07 +08:00
function getPhonePath(data = [], name, prefix = []) {
for (let i = 0, len = data.length; i < len; i++) {
let tmp = data[i];
if (prefix.isFind) return prefix;
prefix.push(tmp.name);
if (tmp.name === name && (prefix.isFind = true)) return prefix;
if (tmp.childs) getPhonePath(tmp.childs, name, prefix)
!prefix.isFind && prefix.pop();
}
return [...prefix];
}

console.log(getPhonePath(data, "HUAWEI Mate 20 X"));

加个标志,可以少一层循环。
nikandaoleshenme
2019-05-21 16:38:33 +08:00
@lyshine 竟然从这跑去 sf 了
redbuck
2019-05-21 17:09:35 +08:00
递归就完了
```
function name2path(list, name, path) {
return list.reduce((prev, item) => {
if (item.name === name) {
return path + '/' + item.name
}
else {
if (item.children) {
return name2path(item.children, name, path + '/' + item.name) || prev
}
return prev
}
}, path)
}
```
redbuck
2019-05-21 17:22:11 +08:00
@redbuck

错了 reduce 第二个参数应该是''

function name2path(list, name, path) {
return list.reduce((prev, item) => {
// ...
}, '')
}
lyshine
2019-05-21 18:01:58 +08:00
@nikandaoleshenme 这都被你发现了. 哈哈哈今天刚注册的
lyshine
2019-05-21 19:26:54 +08:00
@zqx 你可以看 6 楼的, 他的实现就是扁平了结构
lyshine
2019-05-21 19:35:47 +08:00
@zqx 错了 , 是 8 楼的实现
aihimmel
2019-05-21 23:55:55 +08:00
python 写的
def iter_names(a, prefix=''):
for i in a:
if 'childs' in i:
ite(i['childs'], prefix=prefix + i['name'] + '/')
else:
print prefix + i['name']
brucewuio
2019-05-24 15:06:34 +08:00
function retrievePath(phoneName,obj) {
for (let i in obj) {
if (obj[i]['childs']) {
let returnStr = retrievePath(phoneName,obj[i]['childs'])
if (returnStr !== '')
return '/' + obj[i]['name'] + returnStr
}else {
if (phoneName === obj[i]['name']) {
return '/' + obj[i]['name']
}
}
}
}
takemyhate
364 天前
function findPath(data, target) {
let path = ""; // 用于存储路径

function traverse(node, currentPath) {
if (node.name === target) {
path = currentPath; // 找到目标节点时更新路径
return;
}

if (node.childs) {
for (let i = 0; i < node.childs.length; i++) {
const child = node.childs[i];
const newPath = currentPath ? `${currentPath} / ${child.name}` : child.name;
traverse(child, newPath); // 递归遍历子节点
}
}
}

traverse(data, "");

return path;
}

// 测试
var data = [
{
name: "手机",
childs: [
{
name: "iPhone",
childs: [
{ name: "iPhone X" },
{ name: "iPhone XR" },
{ name: "iPhone XS" },
],
},
{
name: "HUAWEI",
childs: [
{ name: "HUAWEI Mate 20" },
{ name: "HUAWEI Mate 20 X" },
{ name: "HUAWEI Mate 20 Pro" },
],
},
],
},
];

console.log(findPath(data[0], "HUAWEI Mate 20")); // 输出 "手机 / HUAWEI / HUAWEI Mate 20"
//findPath 函数接受两个参数:data 是树的根节点,target 是要查找的目标节点的名称。函数通过递归遍历树的节点,每次遍历时更新当前路径,并检查当前节点是否为目标节点,如果是则将路径存储到 path 变量中。最终返回得到的路径。这个可以适用于多层的数据结构,因为它通过递归方式遍历树的每个节点,不论树的深度有多大,都能正确地找到路径。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/566080

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX