javascript 基于属性级别将平面对象数组格式化为嵌套对象数组

vngu2lb8  于 2023-03-21  发布在  Java
关注(0)|答案(1)|浏览(316)

这是输入的数据。

let list = [
    {
        name: "h1",
        level: 1,
        children: []
    },
    {
        name: "h2",
        level: 2,
        children: []
    },
    {
        name: "h3",
        level: 3,
        children: []
    },
    {
        name: "paragraph",
        level: 1,
        children: []
    },
    {
        name: "bold",
        level: 2,
        children: []
    },
    {
        name: "italic",
        level: 2,
        children: []
    },
    {
        name: "paragraph",
        level: 1,
        children: []
    }

]

结果结果是这样的

[
 {
  "name": "h1",
  "level": 1,
  "children": [
   {
    "name": "h2",
    "level": 2,
    "children": [{
         "name": "h3",
         "level": 3,
        "children": []
   }]
    }   
  ]
 },
 {
  "name": "paragraph",
  "level": 1,
  "children": [
   {
    "name": "bold",
    "level": 2,
    "children": []
   },
   {
    "name": "italic",
    "level": 2,
    "children": []
   }
  ]
 },
 {
  "name": "paragraph",
  "level": 1,
  "children": []
 }
]

这是我的尝试。问题是我在迭代之间只携带finalist和当前值。当级别更高时,我将其添加到最后一个item children值。这适用于第一层。但是我如何告诉它检查它的子对象并向下冒泡整个对象以进行正确的插入。
它应该只加到孩子身上,如果它大于,如果它等于,孩子,就把它加到兄弟上,我似乎只能做或者,我有嵌套孩子的代码,但是我不能做兄弟,我在兜圈子。

const initialValue = [];
const output = list.reduce((acc,curr, index,arr)=>{
        console.log(index,"start========:",acc, "||", curr)

        if(index === 0){
            console.log(index, "push first into array")
            return acc.concat([curr])
        }

        console.log(index,"compare level?",acc[acc.length - 1].level,  curr.level)

        if(acc[acc.length - 1].level <  curr.level){
            console.log(index, acc[acc.length - 1].children, "push bold into paragraph")
            acc[acc.length - 1].children.push(curr);
            console.log(index, "check result?", acc)
            return acc
        } else {
            return acc.concat([curr])
        }
        return acc;

}, initialValue

);

console.log("output:",JSON.stringify(output,null, 1))
c3frrgcw

c3frrgcw1#

假设.level的值为i的元素不能被level的值大于i + 1的元素继承:
(this尽可能明确地写出来,以便于解释;更简洁的版本可以在下面的片段中找到)

function makeTreesFromObjects(objects) {
    const stack = [{ children: [] }];

    for (const originalObject of objects) {
        let object = structuredClone(originalObject);

        if (object.level < stack.length - 1) {

            stack.splice(object.level, Infinity, object);
            stack.at(-2).children.push(object);

        } else if (object.level > stack.length - 1) {

            stack.at(-1).children.push(object);
            stack.push(object);

        } else if (object.level === stack.length - 1) {

            stack.at(-2).children.push(object);
            stack.splice(-1, 1, object);

        }
    }

    return stack[0].children;
}

解释

首先,创建一个由“根”元素组成的堆栈;它的子元素将是我们想要的新列表:

const stack = [{ children: [] }];

然后,迭代给定元素的列表,并在我们进行时克隆它们:

for (const originalObject of objects) {
    let object = structuredClone(originalObject);

    // ...
}

如果object(当前元素)比栈顶的元素浅,弹出object之后的所有元素并将其推送到栈中。我们还将其推送到第二个最上面的元素.children,因为它现在已经成为object的父元素:

if (object.level < stack.length - 1) {
    stack.splice(object.level, Infinity, object);
    stack.at(-2).children.push(object);
}

/*

Stack:

-----------------------------------------
|    0    |    1    |    a    |    b    |
-----------------------------------------
| [1]     | [a]     | [b]     | []      |

Current element:
                    -----------
                    |    c    |
                    -----------

After:
-------------------------------
|    0    |    1    |    c    |
-------------------------------
| [1]     | [a, c]  | []      |

*/

如果object更深,则将其推送到堆栈和最顶层元素的.children

if (object.level > stack.length - 1) {
    stack.at(-1).children.push(object);
    stack.push(object);
}

/*

Stack:

-----------------------------------------
|    0    |    1    |    a    |    b    |
-----------------------------------------
| [1]     | [a]     | [b]     | []      |

Current element:
                                        -----------
                                        |    c    |
                                        -----------

After:
---------------------------------------------------
|    0    |    1    |    a    |    b    |    c    |
---------------------------------------------------
| [1]     | [a]     | [b]     | [c]     | []      |

*/

如果object的级别与顶层元素的级别相同,则将object设为新的顶层元素,并将其推到次顶层元素的.children

if (object.level === stack.length - 1) {
    stack.at(-2).children.push(object);
    stack.splice(-1, 1, object);
}

/*

Stack:

-----------------------------------------
|    0    |    1    |    a    |    b    |
-----------------------------------------
| [1]     | [a]     | [b]     | []      |

Current element:
                              -----------
                              |    c    |
                              -----------

After:
-----------------------------------------
|    0    |    1    |    a    |    c    |
-----------------------------------------
| [1]     | [a]     | [b, c]  | []      |

*/

最后,返回bottommost(或“root”)的子节点;这就是我们要的名单

return stack[0].children;

试试看:

function makeTreesFromObjects(objects) {
    const stack = [{ children: [] }];

    for (const originalObject of objects) {
        let object = structuredClone(originalObject);

        stack.splice(object.level, Infinity, object);
        stack.at(-2).children.push(object);
    }

    return stack[0].children;
}

const list = [
    {
        name: 'h1',
        level: 1,
        children: []
    },
    {
        name: 'h2',
        level: 2,
        children: []
    },
    {
        name: 'h3',
        level: 3,
        children: []
    },
    {
        name: 'paragraph',
        level: 1,
        children: []
    },
    {
        name: 'bold',
        level: 2,
        children: []
    },
    {
        name: 'italic',
        level: 2,
        children: []
    },
    {
        name: 'span',
        level: 3,
        children: []
    },
    {
        name: 'a',
        level: 2,
        children: []
    },
    {
        name: 'bold',
        level: 3,
        children: []
    },
    {
        name: 'paragraph',
        level: 1,
        children: []
    }
];

console.log(JSON.stringify(makeTreesFromObjects(list), null, 2));
.as-console-wrapper {
  max-height: 100% !important;
}

相关问题