user2876623
user2876623

Reputation: 83

How can += be used when adding to an object property that may not exist?

Consider an array of objects

myArray = [
  {date: 'date1', amount: 1},
  {date: 'date1', amount: 2},
  {date: 'date2', amount: 3},
  {date: 'date2', amount: 4},
]

I want to end up with values summed in a object like so:

{
  date1: 3,
  date2: 7
}

This works:

let myObj = {}
myArray.forEach(arrayObj=>{
  myObj[arrayObj.date] ? myObj[arrayObj.date] += arrayObj.amount : myObj[arrayObj.date] = obj.amount
})

This would be cleaner but does not work

let myObj = {}
myArray.forEach(arrayObj=>{
  myObj[arrayObj.date] += arrayObj.amount
})

Question: is there a way to do this without checking for the existence of the property?

Upvotes: 1

Views: 45

Answers (2)

georg
georg

Reputation: 215009

You can utilize a Proxy to create a DefaultDict object, similar to that in python. DefaultDict returns a predefined value for missing keys, instead of undefined.

function DefaultDict(value) {
    return new Proxy({}, {
        get(target, key) {
            return key in target ? target[key] : value
        }
    })
}

// example:


myArray = [
  {date: 'date1', amount: 1},
  {date: 'date1', amount: 2},
  {date: 'date2', amount: 3},
  {date: 'date2', amount: 4},
]

myObj = DefaultDict(0)

myArray.forEach(v => myObj[v.date] += v.amount)

console.log(myObj)

Upvotes: 1

CertainPerformance
CertainPerformance

Reputation: 370989

There's no way to get around repeating myObj[arrayObj.date] twice, but you can make things shorter by unconditionally assigning to it, and alternating || it with 0.

myArray = [
  {date: 'date1', amount: 1},
  {date: 'date1', amount: 2},
  {date: 'date2', amount: 3},
  {date: 'date2', amount: 4},
]
const result = {};
for (const { date, amount } of myArray) {
  result[date] = (result[date] || 0) + amount;
}
console.log(result);

Upvotes: 1

Related Questions