5

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. 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.

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?

3 Answers 3

2

The code below first performs a flatMap operation on the nested sources arrays, and then reduces everything to your desired result object:

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)

Sign up to request clarification or add additional context in comments.

Comments

2

You could reduce the outer array and iterate sources and update an object as result set.

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.

Comments

1

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.

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.