如何将嵌套的JSON数据结构简化为地图JavaScript

时间:2018-08-17 04:54:47

标签: javascript json data-structures

我已经使用循环实现了以下问题的解决方案,但是我敢肯定有更好的方法。考虑以下数据结构:

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"
                }
            }
        ]
    }
]

我想学习最有效的方法,将其简化为仅包含uri数组中嵌套statesources值的键值对的映射。最终结果应如下所示:

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" } 
}

我有一个局部解决方案,它返回每个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?
}, {})

在这里可以选择递归还是一种更好的方法?

3 个答案:

答案 0 :(得分:2)

下面的代码首先对嵌套的flatMap数组执行sources操作,然后将所有内容简化为所需的结果对象:

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

完整代码段:

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)

答案 1 :(得分:2)

您可以减少外部数组并迭代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; }

  

在这里可以选择递归还是一种更好的方法?

不,因为您只有一个嵌套级别。

答案 2 :(得分:1)

您可以使用嵌套的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)