代码之家  ›  专栏  ›  技术社区  ›  merrilj

如何将嵌套的JSON数据结构简化为映射JavaScript

  •  3
  • merrilj  · 技术社区  · 6 年前

    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 state sources 阵列。最终结果应该是这样的:

    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 回复  |  直到 6 年前
        1
  •  2
  •   Robby Cornelissen    6 年前

    下面的代码首先执行 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)
        2
  •  2
  •   Nina Scholz    6 年前

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

    递归是这里的一个选项还是更好的方法?

        3
  •  1
  •   Prasanna    6 年前

    可以使用嵌套的reduce-one从列表中的项获取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)