简体   繁体   English

如何将嵌套的JSON数据结构减少为映射JavaScript

[英]How to reduce nested JSON data structure into a map JavaScript

I've implemented a solution for the problem below with loops, but I'm sure there is a better way. 我已经用循环实现了下面问题的解决方案,但我确信有更好的方法。 Consider this data structure: 考虑这个数据结构:

let arr = [
    {
        "id": "000701",
        "status": "No Source Info",
        "sources": []
    },
    {
        "id": "200101",
        "status": "Good",
        "sources": [
            {
                "center": "H2",
                "uri": "237.0.1.133",
                "program": 1,
                "status": "Good",
                "state": {
                    "authState": "authorized",
                    "lockState": "locked"
                }
            }
        ]
    },
    {
        "id": "005306",
        "status": "Good",
        "sources": [
            {
                "center": "H1",
                "uri": "237.0.6.5",
                "program": 3,
                "status": "Good",
                "state": {
                    "authState": "authorized",
                    "lockState": "locked"
                }
            },
            {
                "center": "H1",
                "uri": "237.0.6.25",
                "program": 3,
                "status": "Good",
                "state": {
                    "authState": "authorized",
                    "lockState": "locked"
                }
            }
        ]
    }
]

I want to learn the most efficient way to reduce it to a map with key-value pairs of only the nested uri and state values from the sources array. 我想学习一种最有效的方法,将它减少到一个映射,只使用来自sources数组的嵌套uristate值的键值对。 The final result should look like this: 最终结果应如下所示:

let stateMap = {
    "237.0.1.133": { "authState": "authorized", "lockState": "locked" },
    "237.0.6.5": { "authState": "authorized", "lockState": "locked" },
    "237.0.6.25": { "authState": "authorized", "lockState": "locked" } 
}

I have a partial solution that returns a map of each source array, but I'm struggling to get it all into one structure. 我有一个部分解决方案,返回每个source数组的映射,但我很难将它全部集成到一个结构中。

let allStates = arr.reduce((acc, object) => {
    if (object.sources.length) {
        let sourceMap = object.sources.reduce((map, obj) => {
            map[obj.uri] = obj.state
            return map
        }, {})
        acc[acc.length] = sourceMap
        return acc
    }
    // delete all unused keys and somehow flatten the objects?
}, {})

Would recursion be an option here or what would be a better approach? 递归是一个选项在这里或什么是更好的方法?

The code below first performs a flatMap operation on the nested sources arrays, and then reduces everything to your desired result object: 下面的代码首先对嵌套的sources数组执行flatMap操作,然后将所有内容减少到所需的结果对象:

const result = arr.reduce((a, {sources}) => [...a, ...sources], [])
                  .reduce((a, {uri, state}) => ({...a, [uri]: state}), {});

Complete snippet: 完整代码段:

 const arr = [{ "id": "000701", "status": "No Source Info", "sources": [] }, { "id": "200101", "status": "Good", "sources": [{ "center": "H2", "uri": "237.0.1.133", "program": 1, "status": "Good", "state": { "authState": "authorized", "lockState": "locked" } }] }, { "id": "005306", "status": "Good", "sources": [{ "center": "H1", "uri": "237.0.6.5", "program": 3, "status": "Good", "state": { "authState": "authorized", "lockState": "locked" } }, { "center": "H1", "uri": "237.0.6.25", "program": 3, "status": "Good", "state": { "authState": "authorized", "lockState": "locked" } } ] } ]; const result = arr.reduce((a, {sources}) => [...a, ...sources], []) .reduce((a, {uri, state}) => ({...a, [uri]: state}), {}); console.log(result) 

You could reduce the outer array and iterate sources and update an object as result set. 您可以减少外部数组并迭代sources并更新对象作为结果集。

 var data = [{ id: "000701", status: "No Source Info", sources: [] }, { id: "200101", status: "Good", sources: [{ center: "H2", uri: "237.0.1.133", program: 1, status: "Good", state: { authState: "authorized", lockState: "locked" } }] }, { id: "005306", status: "Good", sources: [{ center: "H1", uri: "237.0.6.5", program: 3, status: "Good", state: { authState: "authorized", lockState: "locked" } }, { center: "H1", uri: "237.0.6.25", program: 3, status: "Good", state: { authState: "authorized", lockState: "locked" } }] }], stateMap = data.reduce( (o, { sources }) => (sources.forEach(({ uri, state }) => o[uri] = state), o), Object.create(null) ); console.log(stateMap); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Would recursion be an option here or what would be a better approach? 递归是一个选项在这里或什么是更好的方法?

No, because you have only one single nested level. 不,因为您只有一个嵌套级别。

you can use nested reduce one for getting the uri map from the item in the list, other for getting the value of sources map. 您可以使用嵌套的reduce来从列表中的项目获取uri映射,其他用于获取源映射的值。

const mappedArray = arr.reduce((acc, item) => ({
  ...acc,
  ...item.sources.reduce((accSource, itemSource) => ({
    ...accSource,
    [itemSource.uri]: itemSource.state,
  }), {})
}), {})

 let arr = [ { "id": "000701", "status": "No Source Info", "sources": [] }, { "id": "200101", "status": "Good", "sources": [ { "center": "H2", "uri": "237.0.1.133", "program": 1, "status": "Good", "state": { "authState": "authorized", "lockState": "locked" } } ] }, { "id": "005306", "status": "Good", "sources": [ { "center": "H1", "uri": "237.0.6.5", "program": 3, "status": "Good", "state": { "authState": "authorized", "lockState": "locked" } }, { "center": "H1", "uri": "237.0.6.25", "program": 3, "status": "Good", "state": { "authState": "authorized", "lockState": "locked" } } ] } ] const mappedArray = arr.reduce((acc, item) => ({ ...acc, ...item.sources.reduce((accSource, itemSource) => ({ ...accSource, [itemSource.uri]: itemSource.state, }), {}) }), {}) console.log(mappedArray) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM