Aren Trot
Aren Trot

Reputation: 479

Iterate nested array of objects, find id and update object matching the id

I have below input as follows. Its an array of objects and each object has states which is also a array of objects. i want to append details inside the states object when the state id matches with the id mentioned below. i.e. 82175746

const input = 
[
    {
        "country": { "id": 87745195, "action": "Analyze" },
        "states": [
            { "id": 83589582, "action": "Verify" },
            { "id": 87335656, "action": "Analyze" }
        ]
    },
    {
        "country": { "id": 83861166, "action": "Verify" },
        "states": [
            { "id": 82175746, "action": "Closed" },
            { "id": 78745158, "action": "Closed" }
        ]
    }
]


const details = { "totalOpenRadars": 1, "totalClosedRadars": 1 }

const id = 82175746

And this is the result i am trying to achieve. Please note that id of 82175746 is compared with all the state ids. once a match is found, details mentioned above is appended as shown below to the matched object.

const result = 
[
    {
        "country": { "id": 87745195, "action": "Analyze" },
        "states": [
            { "id": 83589582, "action": "Verify" },
            { "id": 87335656, "action": "Analyze" }
        ]
    },
    {
        "country": { "id": 83861166, "action": "Verify" },
        "states": [
            { "id": 82175746, "action": "Closed", "details": { "totalOpenRadars": 1, "totalClosedRadars": 1 } },
            { "id": 78745158, "action": "Closed" }
        ]
    }
]

In order to achieve this, I tried this way but I am not able to get the result properly. Can someone please let me know where I went wrong

const result  = input.forEach((element) => {
    element.states.forEach((state) => {
        if(state.id === id) {
            state.details = details
        }

    });
});

Upvotes: 0

Views: 1576

Answers (4)

GMKHussain
GMKHussain

Reputation: 4691

Reusable approaches not only key or value, each possible element with neat and clean way.

you can change array, object key where look into, key where want to match with value, and new key and new value.

const students = [
    {
      "name": "Amoos",
      "skills": [
        { id: 11, name: "html" },
        { id: 12, name: "css" }
      ],
      "sports": [
        {id: 31, name: "football"},
        {id: 32, name: "circket"},
      ]
    },
    {
      "name": "Rifat",
      "skills": [
        { id: 21, name: "reactjs" },
        { id: 22, name: "nextjs" }
      ],
      "sports": [
        {id: 41, name: "baseball"},
        {id: 42, name: "volleyball"},
      ]
    },
]

 

const addNewValueByKeyInArray = (arrayData, where, key, value, newKey, newValue ) => {
   return arrayData.map(( d ) => d[where].map((w) => (w[key] === value) ? {
            ...w, [newKey]: newValue
        } : {...w}
    ))
}

// EXAMPL #1
console.log(addNewValueByKeyInArray(students, 'sports', 'id', 42, 'details', { 'region': 'worldwide', 'first_played': '1895' }));

// EXAMPL #2
console.log(addNewValueByKeyInArray(students, 'skills', 'id', 22, 'details', { 'author': 'Guillermo Rauch', 'first_version': '2016' }));
 

Upvotes: 0

Yosvel Quintero
Yosvel Quintero

Reputation: 19080

You can use Array.prototype.map():

const input = [{"country": { "id": 87745195, "action": "Analyze" },"states": [{ "id": 83589582, "action": "Verify" },{ "id": 87335656, "action": "Analyze" }]},{"country": { "id": 83861166, "action": "Verify" },"states": [{ "id": 82175746, "action": "Closed" },{ "id": 78745158, "action": "Closed" }]}]
const details = { "totalOpenRadars": 1, "totalClosedRadars": 1 }
const id = 82175746

const result = input.map(item => item.states.map(state => ({
  ...state,
  ...(state.id === id ? { details } : {})
})))

console.log(result)

Upvotes: 1

Liftoff
Liftoff

Reputation: 25392

Array.forEach always returns undefined, so result will always be undefined. If you look at input after your operation, it does contain your details as you specified.

Alternatively, you could spread input into a new array called result and perform your loop on result instead if you intend to keep input the same.

const input = 
[
    {
        "country": { "id": 87745195, "action": "Analyze" },
        "states": [
            { "id": 83589582, "action": "Verify" },
            { "id": 87335656, "action": "Analyze" }
        ]
    },
    {
        "country": { "id": 83861166, "action": "Verify" },
        "states": [
            { "id": 82175746, "action": "Closed" },
            { "id": 78745158, "action": "Closed" }
        ]
    }
]


const details = { "totalOpenRadars": 1, "totalClosedRadars": 1 }

const id = 82175746

input.forEach((element) => {
    element.states.forEach((state) => {
        if(state.id === id) {
            state.details = details
        }

    });
});
console.log(input);

Upvotes: 1

R4ncid
R4ncid

Reputation: 7139

this should be do it

const appendDetails = (data, id, details) => 
  data.map(d => {
    return {
      ...d,
      states: d.states.map(s => {
        if(s.id !== id){
          return s
        }
        return {
          ...s,
          details
        }
      })
    } 
  })

const input = 
[
    {
        "country": { "id": 87745195, "action": "Analyze" },
        "states": [
            { "id": 83589582, "action": "Verify" },
            { "id": 87335656, "action": "Analyze" }
        ]
    },
    {
        "country": { "id": 83861166, "action": "Verify" },
        "states": [
            { "id": 82175746, "action": "Closed" },
            { "id": 78745158, "action": "Closed" }
        ]
    }
]


const details = { "totalOpenRadars": 1, "totalClosedRadars": 1 }

const id = 82175746

console.log(appendDetails(input, id, details))

Upvotes: 0

Related Questions