我有一系列的项目如下:
@items = [
{price: 12, quantity:1},
{price: 4, quantity:1},
{price: 8, quantity:1}
]
我正在寻找这样的事情:
sumPrice: ->
@items.sum (item) -> item.price * item.quantity
或者尽可能接近这一点,这使得每个阅读代码的人都能轻松理解发生的事情。
到目前为止,我提出了:
sumPrice: ->
(items.map (a) -> a.price * a.quantity).reduce (a, b) -> a + b
和
sumPrice: ->
sum = 0
for item in items
sum += item.price * item.quantity
sum
我喜欢CoffeeScript,所以我希望有更好的解决方案。我想念的类似场景。
答案 0 :(得分:13)
功能风格并不是那么糟糕。 CoffeeScript允许你像这样美化你的代码:
items
.map (item) ->
item.price * item.quantity
.reduce (x,y) ->
x+y
此代码比单行代码更容易理解。
如果您不喜欢map
,可以改用for
。像这样:
(for item in items
item.price * item.quantity)
.reduce (x,y)->x+y
或者像这样:
prods = for item in items
item.price * item.quantity
prods.reduce (x,y)->x+y
或者您可以为数组添加自己的sum()
方法:
Array::sum = -> @reduce (x,y)->x+y
(item.price * item.quantity for item in items).sum()
答案 1 :(得分:11)
如果您想将解决方案表达为@items.sum (item) -> item.price * item.quantity
,可以向sum
添加Array
方法:
Array::sum = (fn = (x) -> x) ->
@reduce ((a, b) -> a + fn b), 0
sum = @items.sum (item) -> item.price * item.quantity
请注意,我将0
作为reduce
的初始值传递,因此会为每个数组值调用fn
回调。
如果你不喜欢扩展内置对象,我想如果你在自己的函数中提取计算单个数组项的总价格的逻辑,你可以优雅地将总和表示为单个减少:
itemPrice = (item) -> item.price * item.quantity
sum = items.reduce ((total, item) -> total + itemPrice item), 0
答案 2 :(得分:7)
您可以使用解构来略微简化代码:
sumPrice: ->
sum = 0
sum += price * quantity for {price, quantity} in @items
sum
我认为没有办法摆脱sum
的显式初始化。虽然Coffeescript的for
循环语法有助于简化原本会使用map()
的代码,但它实际上没有任何类似的简化reduce()
类型的操作,这就是{{1}在这里做。
正如评论中所提到的,此解决方案优于调用sumPrice
或reduce()
的一个优点是它避免了创建和重复调用函数的开销。
答案 3 :(得分:2)
sum = 0
value = (item) ->
item.price * item.quantity
sum += value(item) for item in @items