-1

I have an array of objects -

[{
    title: "oranges",
    id: 5802537,
    cart: {
      purchased: 3,
      stockTotal: 9
    },
    price: 3,
    department: "fresh fruit and veg"
  },
  {
    title: "pasta",
    id: 5802537,
    cart: {
      purchased: 2,
      stockTotal: 15
    },
    price: 1,
    department: "dry goods"
  },
  {
    title: "eggs",
    id: 5802537,
    cart: {
      purchased: 1,
      stockTotal: 11
    },
    price: 2,
    department: "baking"
  }
]

I am trying to write a function that will get add up all the stockTotal and purchased from each object. I have tried this -

let val = items.reduce(function(previousValue, currentValue) {
  return {
    purchased: previousValue.cart.purchased + currentValue.cart.purchased,
    stockTotal: previousValue.cart.stockTotal + currentValue.cart.stockTotal
  };
});

console.log(val);

However, it says that it cannot read property 'purchased' of undefined and cannot read property 'stockTotal' of undefined. I am wondering if this is because stockTotal and purchased are in their own object within each object in the array?

Ori Drori
  • 183,571
  • 29
  • 224
  • 209
monkeys773
  • 71
  • 1
  • 10
  • _"I have some JSON data like so"_ - No, that's not [JSON](https://www.json.org/json-en.html). That's an array of objects: [What is the difference between JSON and Object Literal Notation?](https://stackoverflow.com/questions/2904131/what-is-the-difference-between-json-and-object-literal-notation) – Andreas May 20 '21 at 10:52
  • The first argument of the `.reduce()` callback is not the "previous" element. It's the **return value** of the callback for the previous element. And that's an object without a `.cart` property. Only on the first execution of the callback `previousValue` would be the an element from the array (the first one), when there's no second argument for the `.reduce()` call - check the [documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) – Andreas May 20 '21 at 10:55
  • @Andreas `JSON.parse('[{"foo":"bar"},{"foo":"bar"}]')`. What prevents OP to have used similar evaluation? – undefined May 20 '21 at 10:56

2 Answers2

1

You need to supply an initial value to the reduce accumulator (previousValue which I've changed to acc), and on each iteration take the current values from the acc (or using 0 as a fallback), and add to it the item's values:

const items = [{"title":"oranges","id":5802537,"cart":{"purchased":3,"stockTotal":9},"price":3,"department":"fresh fruit and veg"},{"title":"pasta","id":5802537,"cart":{"purchased":2,"stockTotal":15},"price":1,"department":"dry goods"},{"title":"eggs","id":5802537,"cart":{"purchased":1,"stockTotal":11},"price":2,"department":"baking"}];

const val = items.reduce(function(acc, currentValue) {
  return {
    purchased: (acc.purchased ?? 0) + currentValue.cart.purchased,
    stockTotal: (acc.stockTotal ?? 0) + currentValue.cart.stockTotal
  };
}, {});

console.log(val);
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
1

const data = [{title:"oranges",id:5802537,cart:{purchased:3,stockTotal:9},price:3,department:"fresh fruit and veg"},{title:"pasta",id:5802537,cart:{purchased:2,stockTotal:15},price:1,department:"dry goods"},{title:"eggs",id:5802537,cart:{purchased:1,stockTotal:11},price:2,department:"baking"}];

let purchased = 0, //set initial values
  stockTotal = 0;
for (let item of data) { // loop items
  purchased += item.cart.purchased; // increment initial values
  stockTotal += item.cart.stockTotal;
}
console.log(purchased, stockTotal);
undefined
  • 1,019
  • 12
  • 24