【问题标题】:JS - convert an array to a multi-level objectJS - 将数组转换为多级对象
【发布时间】:2021-06-05 06:01:45
【问题描述】:

我已经第四天了。

需要

const base = [
    { "rel": 1, "title": "a", "path": "AAA" },
    { "rel": 2, "title": "b", "path": "AAA/BBB" },
    { "rel": 3, "title": "c", "path": "AAA/BBB/CCC" },
    { "rel": 4, "title": "d", "path": "AAA/BBB/DDD" },
    { "rel": 5, "title": "e", "path": "AAA/CCC" },
    { "rel": 6, "title": "f", "path": "BBB" }]

转换为:

{
    "a": {
        "rel": 1,
        "b": {
            "rel": 2,
            "c": {"rel": 3},
            "d": {"rel": 4}
        },
        "e": {"rel": 5}
    },
    "f": {"rel": 6}
}

我之前的代码:

console.log(start(base));

function start(arr, index = 0, lvl = 0, res = {}) {
    let { rel, title, path } = arr[index];

    path = path.split("/");
    const how = path.length;
    let lvlNext = null; if (arr[index + 1]) { lvlNext = arr[index + 1].path.split("/"); lvlNext = lvlNext.length; }

    if (how == lvl) res = { rel }

    if (how > lvl) res[title] = start(arr, index, lvl + 1, res[title]);

    if (lvlNext && how == lvl) return start(arr, index + 1, lvl, res);

    return res
}

通过“递归”来做最有意义,但我后来无法回到顶部(可能甚至有几个)

附言。对不起,我不会写英文

【问题讨论】:

  • 到目前为止你尝试了什么?

标签: javascript arrays recursion replace


【解决方案1】:

更新:问题的更新需要重写将输入数组操作到所需输出对象所需的代码。

这是给你的概念演示。

我首先按路径对输入数组进行排序,以避免在高级元素之前获得低级元素。

然后我使用每个数组元素中的路径数据构建所需布局的地图,并结合titlerel 属性。这使得跟踪新兴树中各种数据的位置变得更加容易。 buildMap() 函数沿路径属性工作,调用自身完成每个较低级别。

一旦地图构建完成,就可以直接递归到树中以创建所需的对象并去除路径数据。这是buildFinal() 函数。

注意:此代码仅在提供的示例数据上运行。在认真使用之前,您应该在更大的样本上对其进行测试。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Recursion again</title>
</head>
<body>
<script>
    (function(){
        "use strict";
        console.log("IIFE executing");


        /**
         * Using the path property of each element, create an object of the right
         * structure. This is necessary since without the path information we can lose
         * track of where we are in the tree
         */
        function buildMap(map, el) {
            // console.log("Processing path; "+el.path);
            let path = el.path.split('/');
            if (path.length) {
                let currentNode = path[0];
                if (path.length === 1) {
                    map.subs = map.subs || {};
                    map.subs[currentNode] = {rel: el.rel, title: el.title}
                } else {
                    if (map.subs[currentNode]) {
                        // Remove the first element from the path and update the element
                        el.path = path.slice(1).join('/');
                        // Call ourselves from where we are.
                        buildMap(map.subs[currentNode],el);
                    } else {
                        throw `Invalid path ${el.path}`
                    }
                }
            } else {
                throw 'No path in element.';
            }
            // console.log(map);
        }

        /**
         * Now recurse the map, extracting the title and rel information to create
         * the required properties in the right places.
         */
        function buildFinal(map, obj) {
            if (map.title) {
                obj.rel = map.rel
            }
            if (map.subs) {
                for (const [path, el] of Object.entries(map.subs)) {
                    obj[el.title] = buildFinal(el, {});
                }
            }
            return obj;
        }

        function sortByPath($arr) {
            return $arr.sort((el1, el2)=>{
                if (el1.path > el2.path) return 1;
                return (el1.path === el2.path?0:-1);
            })
        }
        const base = [
            { "rel": 1, "title": "a", "path": "AAA" },
            { "rel": 2, "title": "b", "path": "AAA/BBB" },
            { "rel": 3, "title": "c", "path": "AAA/BBB/CCC" },
            { "rel": 4, "title": "d", "path": "AAA/BBB/DDD" },
            { "rel": 5, "title": "e", "path": "AAA/CCC" },
            { "rel": 6, "title": "f", "path": "BBB" }]

        // Sort the base array by path to ensure that we get higher elements before lower ones.
        sortByPath(base);
        // console.log(base);

        // Working from the path included in each element, build a map object that places
        // all the data in the right place
        let pathMap = {};
        base.forEach(function(el) {
            buildMap(pathMap, el);
        });

        console.log("Finished building map");
        // console.log(pathMap);

        // Now with the map built we can recurse down it to build the final object
        let finalObject = buildFinal(pathMap, {});
        console.log("Finished building final object");
        console.log(finalObject);
    })();


</script>
</body>
</html>

【讨论】:

  • 非常感谢!!我会尝试将其转化为我的项目
  • 是的 - 我错过了。它应该很容易修复。我会把它留给你,但如果你有问题,请联系我。
  • 我举错了例子,你需要在“路径”中导航
  • 如果您发布更正的示例,我将在此处更新代码。
  • @Atomos672 我重新编写了代码来处理您修改后的示例数据。请看my profile
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-04
  • 2012-05-07
  • 2018-02-06
相关资源
最近更新 更多