JavaScript How to aggregate nested JavaScript object by property?

I have the following JavaScript object:

var example = [{
    country: "US",
    things: {
      weather: 'cloudy'
    }
  },
  {
    country: "US",
    things: {
      resource: 'lead',
      weather: 'sunny'
    }
  },
  {
    country: "MX",
    things: {
      weather: 'sunny'
    }
  },
  {
    country: "MX",
    things: {
      resource: 'gold',
      weather: 'sunny'
    }
  },
  {
    country: "MX",
    things: {
      resource: 'copper'
    }
  },
]

I would like to convert to this format via aggregation.

var out = [{
    country_code: 'US',
    things: {
      resource: ['lead'],
      weather: ['cloudy', 'sunny']
    }
  },
  {
    country_code: 'MX',
    things: {
      resource: ['gold', 'copper'],
      weather: ['sunny'],
    }
  }

]

I have tried to look into using combinations of reduce and map to no avail. It would be great if this example can also serve as a jumping off point for general strategies for data manipulation that may or may not involve the use of the array methods.

Answer:1

Use reduce to iterate over the objects to compile your new object, piecing together the things you want:

const example = [{
    country: "US",
    things: {
      weather: 'cloudy'
    }
  },
  {
    country: "US",
    things: {
      resource: 'lead',
      weather: 'sunny'
    }
  },
  {
    country: "MX",
    things: {
      weather: 'sunny'
    }
  },
  {
    country: "MX",
    things: {
      resource: 'gold',
      weather: 'sunny'
    }
  },
  {
    country: "MX",
    things: {
      resource: 'copper'
    }
  },
]

const out = Object.values(
  example.reduce((a, v) => {
    if (!a[v.country]) {
      a[v.country] = {
        country_code: v.country,
        things: {}
      }
    }

    Object.entries(v.things).forEach(([key, value]) => {
      if (!a[v.country].things[key]) {
        a[v.country].things[key] = []
      }

      if (!a[v.country].things[key].includes(value)) {
        a[v.country].things[key].push(value)
      }
    })

    return a
  }, {})
)

console.log(out)
Answer:2

This will show you how to use reduce to get the data that you want using reduce

const example = [{
    country: "US",
    things: {
      weather: "cloudy"
    }
  },
  {
    country: "US",
    things: {
      resource: "lead",
      weather: "sunny"
    }
  },
  {
    country: "MX",
    things: {
      weather: "sunny"
    }
  },
  {
    country: "MX",
    things: {
      resource: "gold",
      weather: "sunny"
    }
  },
  {
    country: "MX",
    things: {
      resource: "copper"
    }
  }
];

const output = example.reduce((acc, current) => {
  const index = acc.findIndex(x => x.country === current.country);
  if (index === -1) {
    const newNode = {
      country: current.country,
      things: {
        resource: current.things.resource ? [current.things.resource] : [],
        weather: current.things.weather ? [current.things.weather] : []
      }
    };
    acc.push(newNode);
  } else {
    current.things.resource && acc[index].things.resource.findIndex(x => x === current.things.resource) === -1 && acc[index].things.resource.push(current.things.resource)


    current.things.weather && acc[index].things.weather.findIndex(x => x === current.things.weather) === -1 && acc[index].things.weather.push(current.things.weather)
  }
  return acc;
}, []);

console.log(output);
Answer:3

You can use reduce function and use findIndex to check if the accumulator have the object with country_code. If it is there then update the array in things object.

var example = [{
    country: "US",
    things: {
      weather: 'cloudy'
    }
  },
  {
    country: "US",
    things: {
      resource: 'lead',
      weather: 'sunny'
    }
  },
  {
    country: "MX",
    things: {
      weather: 'sunny'
    }
  },
  {
    country: "MX",
    things: {
      resource: 'gold',
      weather: 'sunny'
    }
  },
  {
    country: "MX",
    things: {
      resource: 'copper'
    }
  },
]


function finalOut(arr) {
  return arr.reduce(function(acc, curr) {
    let findIndex = acc.findIndex(function(item) {
      return item.country_code === curr.country;
    });
    if (findIndex === -1) {
      acc.push({
        country_code: curr.country,
        things: {
          resource: curr.things.resource ? [curr.things.resource] : [],
          weather: curr.things.weather ? [curr.things.weather] : []
        }
      })
    } else {

      if (curr.things.resource && acc[findIndex].things.resource.indexOf(curr.things.resource) === -1) {
        acc[findIndex].things.resource.push(curr.things.resource);
      }

      if (curr.things.weather && acc[findIndex].things.weather.indexOf(curr.things.weather) === -1) {
        acc[findIndex].things.weather.push(curr.things.weather);
      }

    }

    return acc;
  }, [])
}

console.log(finalOut(example))
Answer:4

Use reduce to iterate over all the items and then arrange them in the right format:

example.reduce((prev,current)=>{

        let index = prev.findIndex(item => item.country_code == current.country);

        if(index>=0){
            if(current.things.resource && !prev[index].things.resource.includes(current.things.resource))
                prev[index].things.resource.push(current.things.resource);
            if(current.things.weather && !prev[index].things.weather.includes(current.things.weather))
                prev[index].things.weather.push(current.things.weather);
        }else{
            prev.push({
                country_code : current.country,
                things : {
                    weather : current.things.weather ? [current.things.weather] : [],
                    resource : current.things.resource ? [current.things.resource] : []
                }
            });
        }
        return prev;
},[]);
Answer:5

Currently I have the following partial code in my puppeteer file: const getImgSrc = await page.$eval('#ldpGallery', el => el.getElementsByTagName('img')); console.log(getImgSrc); The html I'm ...

Currently I have the following partial code in my puppeteer file: const getImgSrc = await page.$eval('#ldpGallery', el => el.getElementsByTagName('img')); console.log(getImgSrc); The html I'm ...

  1. puppeteer eval function

I have created a modal list using bootstrap and Actually I have a form list created and when entered details, it will land me to a desired page. Register button performs this function. But now I have ...

I have created a modal list using bootstrap and Actually I have a form list created and when entered details, it will land me to a desired page. Register button performs this function. But now I have ...

I am attempting to store html code in a textarea field using jquery with the following code: var text ="<p>Hello, my name is Sam</p>"; var textarea = d.createElement( 'textarea' ); // ...

I am attempting to store html code in a textarea field using jquery with the following code: var text ="<p>Hello, my name is Sam</p>"; var textarea = d.createElement( 'textarea' ); // ...

  1. jquery fill textarea value
  2. jquery fill textarea
  3. jquery fill textarea with text
  4. jquery populate textarea

I have this multi dimensional array of objects - const initialArray = [ { name: 'aaa', value:[{id:1, data:1}, {id:2, data:2}, {id:3, data:3}] }, { name: 'bbb', value:[{id:1, data:...

I have this multi dimensional array of objects - const initialArray = [ { name: 'aaa', value:[{id:1, data:1}, {id:2, data:2}, {id:3, data:3}] }, { name: 'bbb', value:[{id:1, data:...

  1. reduce multidimensional array javascript
  2. reduce multidimensional array php
  3. reduce multidimensional array
  4. mpi_reduce multidimensional array
  5. how to reduce multidimensional poverty
  6. matlab reduce multidimensional array