为了账号安全,请及时绑定邮箱和手机立即绑定

JS 递归映射对象名称

JS 递归映射对象名称

慕的地6264312 2022-01-01 18:33:18
我有一组对象,具有未定义的深度。现在我希望名称输出如下:Top LevelTop Level > Sub 1Top Level > Sub 1 > Sub 1-2Top Level > Sub 2但是,我总是只得到最低的元素。我不知道我还可以更改什么来正确格式化名称。        parseCategories(categories, stackCounter = 0) {          categories.forEach(c => {            this.res[stackCounter] = { name: c.attributes.name, id: c.id };            if(c.children.length >= 1) {              this.parseCategories(c.children, stackCounter + 1);            }          });          return this.res;        }我的对象看起来像这样:{   "data":[      {         "type":"categories",         "id":"1",         "attributes":{            "name":"Top Level"         },         "children":[            {               "type":"categories",               "id":"2",               "attributes":{                  "name":"Sub 1"               },               "children":[                  {                     "type":"categories",                     "id":"4",                     "attributes":{                        "name":"Sub 1-2"                     },                     "children":[                     ]                  }               ]            },            {               "type":"categories",               "id":"3",               "attributes":{                  "name":"Sub 2"               },               "children":[               ]            }         ]      }   ]}
查看完整描述

2 回答

?
弑天下

TA贡献1818条经验 获得超8个赞

通常生成器函数会简化这种遍历。在这里,我们可以编写一个非常简单的生成器,然后将其包装在一个函数中,该函数从该生成器创建一个数组:


const getPaths = function * (xs, ps = []) {

  for (let x of xs) {

    yield [... ps, x .attributes .name] .join (' > ')

    yield * getPaths (x .children, [...ps, x .attributes .name])

  }

}


const categoryNames = (categories) => 

  [... getPaths (categories .data)]


const categories = {data: [{type: "categories", id: "1", attributes: {name: "Top Level"}, children: [{type: "categories", id: "2", attributes: {name: "Sub 1"}, children: [{type: "categories", id: "4", attributes: {name: "Sub 1-2"}, children: []}]}, {type: "categories", id: "3", attributes: {name: "Sub 2"}, children: []}]}]};


console .log (

  categoryNames(categories)

)


getPaths通过删除join (' > ')调用并将其添加map到categoryNames. 但是由于children和attributes.names已经是针对特定问题的,我可能不会打扰。


解释

你说你没有完全遵循这个代码。这是试图解释它。如果我解释一些你已经理解的东西,请不要生气。我不清楚到底需要解释什么。


外部函数categoryNames是一个非常小的包装器getPaths。那个做所有的工作。


有两个重要特征需要注意getPaths:


它是一个生成器函数,由关键字和参数列表*之间的function符号表示。Generator 函数创建Generator对象,因为它们符合 [可迭代协议],所以可以在诸如let x of generatorand 之类的结构中使用[...generator]。这就是categoryNames将 的输出getPaths转换为数组的方式。(顺便说一句,可迭代协议也是for-of循环中如何getPaths将数组转换为值序列的方式。)生成器函数通过yielding 单个值或使用yield * anotherGenerator单独生成另一个生成器产生的每个值来工作。在这些yield调用之间,函数被挂起,直到请求下一个值。


它是一个递归函数;函数体再次调用同一个函数,参数更简单。大多数情况下,在递归函数中,您会看到一个显式的基本情况,当输入足够简单时,直接返回答案而无需递归调用。这里的基本情况是隐含的。Whenxs是一个空数组,for-loop永远不会调用的主体,因此递归结束。


getPaths接受一个值数组(xs是我的未知类型值列表的默认名称;nodes也是一个好名字)并且它接受一个字符串数组,表示层次结构中直到当前节点的路径。例如,它可能包含["Top Level", "Sub 1"]. 请注意,这是一个默认参数;如果你不提供它,它会得到一个空数组。


我们遍历提供给我们的值。对于每一个,我们首先通过在它们之间穿插来产生组合当前路径和我们当前对象name的attribute属性的结果" > "。然后我们通过传递孩子和包括当前名字在内的一组名称来递归,依次产生它的每个孩子。这个版本的性能可能稍高一些,也更容易阅读:


const getPaths = function * (xs, paths = []) {

  for (let x of xs) {

    const newPaths = [... paths, x .attributes .name]

    yield newPaths .join (' > ')

    yield * getPaths (x .children, newPaths)

  }

}

如果你愿意,你可以这样定义newPaths:


    const newPaths = paths .concat (node .attributes .name)

我希望这有帮助。如果您对此有任何疑问,请添加评论。


查看完整回答
反对 回复 2022-01-01
?
繁星coding

TA贡献1797条经验 获得超4个赞

看这块


categories.forEach(c => {

  this.res[stackCounter] = { name: c.attributes.name, id: c.id };

});

你可以看到它res[stackCounter]总是被 的最后一个元素覆盖categories。要解决这个问题,也res[stackCounter]应该是一个数组。


parseCategories(categories, stackCounter = 0) {

  // init res[stackCounter]

  if (this.res[stackCounter]) {

    this.res[stackCounter] = [];

  }

  categories.forEach(c => {

    this.res[stackCounter].push({ name: c.attributes.name, id: c.id }); // push to res[stackCounter]

    if(c.children.length >= 1) {

      this.parseCategories(c.children, stackCounter + 1);

    }

  });

  return this.res;

}


查看完整回答
反对 回复 2022-01-01
  • 2 回答
  • 0 关注
  • 217 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信