【问题标题】:Iterate nested objects dynamically and push the specific values into separate array using recursion动态迭代嵌套对象并使用递归将特定值推送到单独的数组中
【发布时间】:2020-03-26 22:42:17
【问题描述】:

我正在尝试基于键返回值数组的 java 脚本递归函数。

嵌套的 JavaScript 对象的深度未知。该函数正在运行,但该值未正确返回..当我从另一个函数调用此递归函数时,我只获得了第一个迭代值。但我可以控制台并查看同一函数中的值。

这是我的 json

{
    "id": 0,
    "name": "Root Entity",
    "children": [{
        "id": 1,
        "name": "REAT",
        "children": [{
            "id": 2,
            "name": "Business",
            "children": [{
                "id": 3,
                "name": "Region 1",
                "children": [{
                    "id": 5,
                    "name": "Area 1",
                    "children": [
                    {
                        "dealerId": 14,
                        "name": "lead 1"
                    }, 
                    {
                        "dealerId": 15,
                        "name": "lead 2"
                    }, 
                    {
                        "dealerId": 16,
                        "name": "lead 3"
                    }, 
                    {
                        "dealerId": 17,
                        "name": "lead 4"
                    }, 
                    {
                        "dealerId": 18,
                        "name": "lead 5"
                    }, 
                    {
                        "dealerId": 19,
                        "name": "lead 6"
                    }, {
                        "dealerId": 20,
                        "name": "lead 7"
                    }],
                    "kpi_1_met": 0,
                    "lead_num": 0,
                }, {
                    "id": 6,
                    "name": "Area 2",
                    "children": [{
                        "dealerId": 31
                        "name": "lead 1"
                    }] 
                }]
            }]
        }]
    }]

}

这是我尝试过的递归函数

async function outputArray(output, leadInfo, req, res) {
    let resoutput = output.children,
        constructedArray = [],
        obj = {};
        // dealerName, entityList = await entityNames(req, res);
    let leagueData = [];

    resoutput.forEach((dataArray) => {
        if (dataArray.hasOwnProperty('children') &&
            dataArray.children instanceof Array &&
            dataArray.children.length > 0) {
            // console.log("================ dataArray.children", dataArray.children[0]['name']);
            for (let i in dataArray.children) {
                obj = { 'regionId': dataArray.children[i].id, 'region': dataArray.children[i].name};
                outputArray(dataArray.children[i], leadInfo, req, res);
                leagueData.push(obj);
                // console.log("================ leagueData ===============", leagueData);
            }

        } else {
            if (dataArray.hasOwnProperty('name'))
                // console.log("================ else", dataArray.name);
        }
    });
    // console.log("================ leagueData outside =============", leagueData);
    return leagueData;
}

我在下面的另一个函数中调用上面的递归函数

async function dataTable(output, leadInfo, req, res) {
    let obj = {},
        data = await outputArray(output, leadInfo, req, res, obj);

    // here First Iterated data only coming
    // console.log("data from data Table", data)
}    

输出应该是

[ 
  { regionId: 3, areaId: 5, dealerId: 14, name: 'lead 1', region: 'Region 1', area: 'Area 1' }, 
  { regionId: 3, areaId: 5, dealerId: 31, name: 'lead 1', region: 'Region 1', area: 'Area 2' } 
]

应该根据树的层次来填充

请任何人帮助我。我正在努力把它弄出来。

【问题讨论】:

  • 你想要怎样的输出数组?是不是像 { id: 0, name: 'Root Entity' }
  • 不应该是 [{ id: 0, name: 'Root Entity' }, { id: 1, name: 'REAT' } ]
  • 我发布了答案检查一次。
  • 我不知道如何将您想要为各个级别生成 areaIdregionIddealer 等字段名称的概念与“嵌套的 JavaScript物体的深度未知。”鉴于“区域”、“经销商”等不在数据中,您如何协调这两者?
  • @ScottSauyet 每个对象都有 id..您可以在区域上方和区域上方看到 id ..每个对象都有名称 例如)“名称”:“区域 1”在区域 1 中它有区域 1 ,区域 2。和区域 2 它有区域 1 区域 2 等等...它就像基于层次结构展平数组 如果区域为 1 并且区域是什么,名称在区域 1 它应该属于区域 1

标签: javascript arrays node.js json recursion


【解决方案1】:

这可能是你正在寻找的

let a = {
    "id": 0,
    "name": "Root Entity",
    "children": [{
        "id": 1,
        "name": "REAT",
        "children": [{
            "id": 2,
            "name": "Business",
            "children": [{
                "id": 3,
                "name": "Region 1",
                "children": [{
                    "id": 5,
                    "name": "Area 1",
                    "children": [
                    {
                        "id": 14,
                        "name": "lead 1"
                    }, 
                    {
                        "id": 15,
                        "name": "lead 2"
                    }, 
                    {
                        "id": 16,
                        "name": "lead 3"
                    }, 
                    {
                        "id": 17,
                        "name": "lead 4"
                    }, 
                    {
                        "id": 18,
                        "name": "lead 5"
                    }, 
                    {
                        "id": 19,
                        "name": "lead 6"
                    }, {
                        "id": 20,
                        "name": "lead 7"
                    }],
                    "kpi_1_met": 0,
                    "lead_num": 0,
                }, {
                    "id": 6,
                    "name": "Area 2",
                    "children": [{
                        "id": 31,
                        "name": "lead 1"
                    }] 
                }]
            }]
        }]
    }]

}


function test(data) {
            let response = [];
            if (Array.isArray(data)) {
                for (let o of data) {
                    response.push({ id: o.id, name: o.name });
                    if (o.hasOwnProperty('children') && o.children.length > 0) {
                        let child = test(o.children);
                        response = response.concat(child);
                    }
                }
            } else {
                response.push({ id: data.id, name: data.name });
                if (data.hasOwnProperty('children') && data.children.length > 0) {
                    let child = test(data.children);
                    response = response.concat(child);
                }
            }
            return response;
        }
   
        let res = test(a);
        console.log(res)

【讨论】:

  • @Ramyachinna 签入 sn-p
  • ..这些值是从递归返回的,但我也得到了一些未定义的值 [ { id: 0, name: 'Root Entity', result: 0 }, { id: 1, name: ' SEAT', result: 0 }, { id: 2, name: 'Business', result: 0 }, { id: 3, name: 'Region 1', result: 0 }, { id: 5, name: '区域1',结果:0 },{ id:未定义,名称:未定义,结果:0 },{ id:未定义,名称:未定义,结果:0 },{ id:未定义,名称:未定义,结果:0 }, { id: undefined, name: undefined, result: 0 } { id: 7, name: 'Area 3', result: 0 } 这样..我不知道为什么
  • 您可以添加数据检查,例如是否存在字段数据,然后仅将数据推送到响应。
  • 我需要像这样格式化输出 [ { regionId: 3, areaId: 5, DealerId: 14, name: 'lead 1', region: 'Region 1', area: 'Area 1' }, { regionId: 3, areaId: 5, DealerId: 31, name: 'lead 1', region: 'Region 1', area: 'Area 2' } ] 应根据树的层次结构填充跨度>
【解决方案2】:

你应该保存递归调用的结果

outputArray(dataArray.children[i], leadInfo, req, res);

【讨论】:

    【解决方案3】:

    我不确定我的问题是否正确。如果您只想迭代数据并将其推送到数组,则以下代码将有所帮助。

    <script>
    var data = {
        "id": 0,
        "name": "Root Entity",
        "children": [{
            "id": 1,
            "name": "REAT",
            "children": [{
                "id": 2,
                "name": "Business",
                "children": [{
                    "id": 3,
                    "name": "Region 1",
                    "children": [{
                        "id": 5,
                        "name": "Area 1",
                        "children": [
                        {
                            "id": 14,
                            "name": "lead 1"
                        }, 
                        {
                            "id": 15,
                            "name": "lead 2"
                        }, 
                        {
                            "id": 16,
                            "name": "lead 3"
                        }, 
                        {
                            "id": 17,
                            "name": "lead 4"
                        }, 
                        {
                            "id": 18,
                            "name": "lead 5"
                        }, 
                        {
                            "id": 19,
                            "name": "lead 6"
                        }, {
                            "id": 20,
                            "name": "lead 7"
                        }],
                        "kpi_1_met": 0,
                        "lead_num": 0
                    }, {
                        "id": 6,
                        "name": "Area 2",
                        "children": [{
                            "id": 31,
                            "name": "lead 1"
                        }] 
                    }]
                }]
            }]
        }]
    
    }
    let leagueData = [];
    function outputArray(output, leadInfo, req, res) {
        let resoutput = output.children,
            obj = { 'regionId': output.id, 'region': output.name};                
            leagueData.push(obj);
            if (output.hasOwnProperty('children') &&
                output.children instanceof Array &&
                output.children.length > 0) {            
                for (let i in output.children) {                
                    console.log("*************** leagueData ===============", output.children[i]);
                    outputArray(output.children[i], leadInfo, req, res);
                }
    
            }
    
    }
     function dataTable(output, leadInfo, req, res) {
        let obj = {},
            data =  outputArray(output, leadInfo, req, res, obj);
        // here First Iterated data only coming
         console.log("data from data Table", leagueData)
    } 
    dataTable(data,"","","");
    </script>
    

    【讨论】:

      【解决方案4】:

      我并不完全清楚这是否是您正在寻找的东西,但这里有一种技术可以使层次结构变平,将祖先名称/ID 压缩到叶节点的属性中:

      const nameToKey = (name) => 
        name .replace(/\s*\d+$/, '') .toLowerCase ()
      
      const flattenHierarchy = (node, desc = {}, {name, id, children} = node) =>
        children && children .length > 0
          ? children .flatMap (child => flattenHierarchy (child, {
              ...desc,
              [nameToKey (name)]: name,
              [nameToKey (name) + 'Id']: id
            }))
          : [{...desc, ...node}]
      
      const data = {"children": [{"children": [{"children": [{"children": [{"children": [{"dealerId": 14, "name": "lead 1"}, {"dealerId": 15, "name": "lead 2"}, {"dealerId": 16, "name": "lead 3"}, {"dealerId": 17, "name": "lead 4"}, {"dealerId": 18, "name": "lead 5"}, {"dealerId": 19, "name": "lead 6"}, {"dealerId": 20, "name": "lead 7"}], "id": 5, "kpi_1_met": 0, "lead_num": 0, "name": "Area 1"}, {"children": [{"dealerId": 31, "name": "lead 1"}], "id": 6, "name": "Area 2"}], "id": 3, "name": "Region 1"}], "id": 2, "name": "Business"}], "id": 1, "name": "REAT"}], "id": 0, "name": "Root Entity"}
      
      console .log (flattenHierarchy (data))

      这会生成一个如下所示的对象数组:

        {
          "root entity": "Root Entity",
          "root entityId": 0,
          "reat": "REAT",
          "reatId": 1,
          "business": "Business",
          "businessId": 2,
          "region": "Region 1",
          "regionId": 3,
          "area": "Area 1",
          "areaId": 5,
          "dealerId": 14,
          "name": "lead 1"
        }
      

      在基本情况下,当我们位于children -&gt; children -&gt; children 层次结构中的叶节点时,我们返回我们构建的对象,并附加了叶节点的所有属性。如果我们不在叶子上,那么我们将当前的 name/id 属性附加到我们的工作对象,并使用这个增强的工作对象递归地调用每个孩子的函数,然后 flatMap 将它们的结果放入单个数组中。

      这与您建议的输出不完全匹配。首先,有更多结果,输入中的每个叶节点都有一个结果。我猜这很好,你只是提供样本而不是完整的预期结果。如果不是,您根据什么标准选择要返回的节点?其次,这里包含的层次结构中还有几个附加属性,例如reatIdroot entity。如果您不希望这些在输出中,您如何决定排除它们?

      最后,虽然我尝试将名称转换为有用的键,但这只是猜测,而且感觉不对。将字符串数据值转换为对象键让我担心;但也许这正是你想要的。

      【讨论】:

        猜你喜欢
        • 2019-08-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-02
        • 1970-01-01
        • 1970-01-01
        • 2021-11-06
        相关资源
        最近更新 更多