从对象数组创建嵌套对象 [已关闭]

create a nested object from array of objects [closed]

提问人:Srilatha Danalakota 提问时间:9/26/2023 最后编辑:evolutionxboxSrilatha Danalakota 更新时间:9/26/2023 访问量:62

问:


想改进这个问题吗?通过编辑这篇文章添加详细信息并澄清问题。

上个月关闭。

let list=[{key1,children[]},{key2,children[]},{key3,children[]}]

如何使用 javascript 获得这样的数组?

list1=[{key1,children[{key2,children[{key3,children[]}]}]}

我试过这样

for (let i = 0; i < list.length; i++) {
  if (list[i + 1]) {
    list[0].children.push(list[i + 1]);
  }
}

但它把所有的孩子都推入了list[0].children

JavaScript 数组 对象 嵌套

评论

3赞 evolutionxbox 9/26/2023
输入和输出都有语法错误,请您修复它们吗?
0赞 Wimanicesir 9/26/2023
但它将所有子项都推入列表[0].children您不会在循环中更改 list[0].children。如果它开始将您的数据推送到其他地方,那就太奇怪了。

答:

0赞 Jamiec 9/26/2023 #1

您需要以相反的顺序处理原始列表,应该这样做:

let list=[{"key":"key1", "children":[]},{"key":"key2", "children":[]},{"key":"key3", "children":[]}]

let result = list.reverse().reduce( (acc,x,i, e) => {
   if(i == list.length-1){
      acc.push(x);
   }
   else{
      e[i+1].children = [x]
   }
   return acc;
   
},[]);


console.log(result);

0赞 Mr. Polywhirl 9/26/2023 #2

这是 Jamiec 答案的替代解决方案。

当数据被转换时,它不会发生变异,因为创建了 。我还从右到左减少了,因为当到达时,我们将返回]。我们确实需要为 reducer 初始化值设置一个非值。该值将起作用。liststructuredCloneindex0[itemundefinednull

当 大于 时,将 作为 推到它的左侧。index0itemchild

const list = [
  { key: "key1", children: [] },
  { key: "key2", children: [] },
  { key: "key3", children: [] }
]

const transformed = structuredClone(list)
  .reduceRight((acc, item, index, ref) => {
    if (index === 0) return [item];
    ref[index - 1].children.push(item);
  }, null);

console.log(transformed);
.as-console-wrapper { top: 0; max-height: 100% !important; }

@Jamiec,您可以更改索引,而不是反转列表。小心,这仍然修改了原来的数组!list

const list = [
  { key: "key1", children: [] },
  { key: "key2", children: [] },
  { key: "key3", children: [] }
]

let result = list.reduce((acc, x, i, e) => {
  if (i === 0) {
    acc.push(x);
  } else {
    e[i - 1].children = [x]
  }
  return acc;
}, []);

console.log(result);
.as-console-wrapper { top: 0; max-height: 100% !important; }

0赞 Alexander Nenashev 9/26/2023 #3

不惜一切代价避免,因为除非您希望保留对象引用,否则克隆对象是一种缓慢的方法。而是在充当数据而不是功能对象的数据上使用。 对于您的情况,如果您想要数据的副本,只需创建您的自定义函数:structuredClone()JSON.parse(JSON.stringify(object))clone()

const list = [
  { key: "key1", children: [] },
  { key: "key2", children: [] },
  { key: "key3", children: [] }
]

const clone = elem => ({key:elem.key, children:[...elem.children]});

const result = [];
let head = result[0] = clone(list[0]);
for(let i = 1; i < list.length; i++){
  head.children.push(head = clone(list[i]));
}
console.log(result);
.as-console-wrapper { top: 0; max-height: 100% !important; }

基准测试速度提高 33 倍:structuredClone()

Cycles: 600000 / Chrome/117
---------------------------------------------------------
Alexander     38/min   1.0x    40    40    38    41    45
Polywhirl   1251/min  32.9x  1308  1272  1289  1251  1266
---------------------------------------------------------
https://github.com/silentmantra/benchmark

<script benchmark="600000">

const list = [
  { key: "key1", children: [] },
  { key: "key2", children: [] },
  { key: "key3", children: [] }
]

// @benchmark Polywhirl

structuredClone(list)
  .reduceRight((acc, item, index, ref) => {
    if (index === 0) return [item];
    ref[index - 1].children.push(item);
  }, null);


// @benchmark Alexander

const clone = elem => ({key:elem.key, children:[...elem.children]});

const result = [];
let head = result[0] = clone(list[0]);
for(let i = 1; i < list.length; i++){
  head.children.push(head = clone(list[i]));
}
result;
</script>
<script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>

评论

0赞 Alexander Nenashev 9/29/2023
@SrilathaDanalakota如果我的答案对你有用,请不要忘记接受它(复选框),谢谢!stackoverflow.com/help/someone-answers