Alex Rivera | Logout

Elegantly do a sum of object attributes in CoffeeScript

Asked 2012-12-19T10:54:29.870
16

I have an array of items like so:

@items = [
  {price: 12, quantity:1}, 
  {price: 4, quantity:1}, 
  {price: 8, quantity:1}
]

And I am looking for something like this:

sumPrice: ->
  @items.sum (item) -> item.price * item.quantity

Or anything as close as possible to this, that makes it super-easy for everyone reading the code to understand whats happening.

So far I came up with:

sumPrice: ->
   (items.map (a) -> a.price * a.quantity).reduce (a, b) -> a + b
  • contains too much functional magic
  • loses descriptiveness

And:

sumPrice: ->
   sum = 0
   for item in items
     sum += item.price * item.quantity
   sum
  • which can be understood by novice JS/Coffee programmers
  • feels a bit stupid

I love CoffeeScript so I hope there is a nicer solution to this & similar scenarios that I miss.

Edit
Report

1 Answer

14

Functional style is not so bad. CoffeeScript allows you to prettify your code like this:

items
  .map (item) ->
    item.price * item.quantity
  .reduce (x,y) ->
    x+y

This code is easier for understanding than your one-liner.

If you don't like map you can use for instead. Like this:

(for item in items
  item.price * item.quantity)
  .reduce (x,y)->x+y

Or like this:

prods = for item in items
  item.price * item.quantity
prods.reduce (x,y)->x+y

Or you can add your own sum() method for arrays:

Array::sum = -> @reduce (x,y)->x+y
(item.price * item.quantity for item in items).sum()
answered 2012-12-19T12:19:35.620

Your Answer