Search code examples
javascriptarraysobject

Is there a better way to combine 2 objects into 1 new array of objects?


I have 2 objects, as such:

costsObj = {
  Honda: 24000,
  BMW: 55000,
  Toyota: 22000
};

stockObj = {
  Honda: 5,
  BMW: 1,
  Toyota: 2
}

I want to combine the 2 objects into 1 array of objects that looks like:

carsArr = [
  {brand: "Honda", cost: 24000, stock: 5},
  {brand: "BMW", cost: 55000, stock: 1},
  {brand: "Toyota", cost: 22000, stock: 2}
]

I have achieved this by using map(), for(), and forEach():

  // Use costsObj to create new array
  carsArr = Object.keys(costsObj).map(brand => {
    return { brand, cost: costsObj[brand], stock: 0 };
  });

  // Add data from stockObj to new carsArr
  for (const [key, value] of Object.entries(stockObj)) {
    carsArr.forEach((item, index)=>{
      if(item.term == key) {
        carsArr[index].stock = value;
      }
    })
  };

But this feels clunky and that there could/should be a better way, especially if I want to combine data from more objects in the future, eg:

carsArr = [
  {brand: "Honda", model: "Accord", cost: 24000, stock: 5},
  {brand: "BMW", model: "3 series", cost: 55000, stock: 1},
  {brand: "Toyota", model: "Camry", cost: 22000, stock: 2}
]

Does anyone know if there is a better way to combine the data from many objects into one array of objects?


Solution

  • You can do it in one line like this:

    const cost = {
      Honda: 24000,
      BMW: 55000,
      Toyota: 22000
    }
    
    const stock = {
      Honda: 5,
      BMW: 1,
      Toyota: 2
    }
    
    const model = {
      Honda: 'Accord',
      BMW: '3 series',
      Toyota: 'Camry'
    }
    
    const cars = Object.entries({model, cost, stock}).reduce((a, [b, c]) =>
      (Object.entries(c).forEach(([d, e]) => (a[d]??={brand: d})[b] = e), a), {})
    
    console.log(Object.values(cars))

    It looks at each of the input objects, and considers the name of the object to be the same as the key that will appear in the final result. Therefore, the object cost will have entries using the key cost: in the result.

    It uses reduce to iterate over values and place them in an object keyed by the brand. It then uses Object.values() to get just the values of that object, once it has been built.