简体   繁体   中英

A better way to deal with objects using many nested forEach?

I would like to know if there is a better way to deal with nested forEach when it comes to dealing with objects with properties that are nested arrays themselves.

My object (summarized):

{
 ...,
 "tx_responses": [
   {
     ...
     "logs" : [
       {
         ...,
         "events": [
             {
                 "type": "coin_received",
                 "attributes": [
                     {
                         "key": "receiver",
                         "value": "somesome"
                     },
                     {
                         "key": "amount",
                         "value": "somesome"
                     }
                 ]
             },
             ...
             {
                 "type": "transfer",
                 "attributes": [
                     {
                         "key": "recipient",
                         "value": "somesome"
                     },
                     {
                         "key": "sender",
                         "value": "somesome"
                     },
                     {
                         "key": "amount",
                         "value": "somesome"
                     }
                 ]
             },
             {
                 "type": "withdraw_rewards",
                 "attributes": [
                     {
                         "key": "amount",
                         "value": "somesomesomehere"
                     },
                     {
                         "key": "validator",
                         "value": "somesome"
                     }
                 ]
             },
             ...
         ]
     }
 ],
...

I am essentially trying to extract all { key: 'amount', value: 'somesomesomehere' } objects in the "attributes" array of the "type": "withdraw_rewards" object in the "events" array.

Currently this is the code I wrote to carry out my task:

getWithdrawnAmounts: async(del_addr_) => {
    let withdrawnAmounts = [];
    const res = await axios.get("some_url_that_uses_del_addr_");
    res.data.tx_responses.forEach(txr => {
        txr.logs.forEach(log => {
            log.events.forEach(evnt => {
                if (evnt.type == "withdraw_rewards") {
                    evnt.attributes.forEach(attr => {
                        if (attr.key == "amount") {
                            withdrawnAmounts.push(attr);
                        }
                    })
                }
            })
        })
    });
    return withdrawnAmounts;
}

The code helps me to get what I need, but I was wondering if there is a better way to write my code so that I dont have to use so many nested .forEach methods. I was wondering if I should use .flat() or .flatMap() but I'm curious to know how would people approach this?

Thank you!

You are going to have to call some kind of iteration for each level you're going deeper.

Now, there is a more functional way to get the desired data, using flatMap and filter :

 const data = { "tx_responses": [{ "logs": [{ "events": [{ "type": "coin_received", "attributes": [{ "key": "receiver", "value": "somesome" }, { "key": "amount", "value": "somesome" }]}, { "type": "transfer", "attributes": [{ "key": "recipient", "value": "somesome" }, { "key": "sender", "value": "somesome" }, { "key": "amount", "value": "somesome" }]}, { "type": "withdraw_rewards", "attributes": [{ "key": "amount", "value": "somesomesomehere" }, { "key": "validator", "value": "somesome" }]}]}]}]}; const result = data.tx_responses.flatMap(r => r.logs.flatMap(l => l.events.filter(e => e.type === 'withdraw_rewards').flatMap(e => e.attributes.filter(a => a.key === 'amount')) ) ); console.log(result);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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