Search code examples
javascriptlodashextract

Lodash extract value from nested object


I have below object which I am currently looping through to get item value. Currently I am using lodash _.forEach to achieve this. I am not sure what is best possible to create a new object with item name as key and value as value.

data =  [
  {
     "panels" : [
        {
          "title": "Panel 1",
          "items" : [
              {
                 "name": item1,
                 "value": 1
              }
              {
                 "name": item2,
                 "value": 2
              }
           ]
         },
         {
            "title": "Panel 2",
             "items" : [
              {
                 "name": item3,
                 "value": 3
              }
              {
                 "name": item4,
                 "value": 5
              }
           ]
         }
     ]
  }

  {
     "panels" : [
        {
          "title": "Panel 3"
          "items" : [
              {
                 "name": item5,
                 "value": 5
              }
              {
                 "name": item6,
                 "value": 6
              }
           ]
        }
     ]
  }  
]

  let values = [];
    _.forEach(data, (groups) => {
        _.forEach(groups.panels, (panel) => {
            _.forEach(panel.items, (item) => {
                  values[item.name] = item.value;                   
            });
        });
    });
    return values;

Is there any other way I can achieve this in more efficient way ?


Solution

  • You could use a nested for...of loops with destructuring

    const data=[{panels:[{title:"Panel 1",items:[{name:"item1",value:1},{name:"item2",value:2}]},{title:"Panel 2",items:[{name:"item3",value:3},{name:"item4",value:5}]}]},{panels:[{title:"Panel 3",items:[{name:"item5",value:5},{name:"item6",value:6}]}]}];
    
    const output = {};
    
    for (const { panels } of data)
      for (const { items } of panels)
        for (const { name, value } of items)
          output[name] = value;
    
    console.log(output)

    Or,

    You could use a chained flatMap to get an array of items. Then reduce the items array to get an object with name as key and value as it's value

    const data=[{panels:[{title:"Panel 1",items:[{name:"item1",value:1},{name:"item2",value:2}]},{title:"Panel 2",items:[{name:"item3",value:3},{name:"item4",value:5}]}]},{panels:[{title:"Panel 3",items:[{name:"item5",value:5},{name:"item6",value:6}]}]}];
    
    const output = data.flatMap(o => o.panels)
                       .flatMap(p => p.items)
                       .reduce((acc, o) => ({ ...acc, [o.name]: o.value }), {})
    
    console.log(output)