优雅地在CoffeeScript中执行一些对象属性

hak*_*nin 16 coffeescript

我有一系列的项目如下:

@items = [
  {price: 12, quantity:1}, 
  {price: 4, quantity:1}, 
  {price: 8, quantity:1}
]
Run Code Online (Sandbox Code Playgroud)

我正在寻找这样的事情:

sumPrice: ->
  @items.sum (item) -> item.price * item.quantity
Run Code Online (Sandbox Code Playgroud)

或者尽可能接近这一点,这使得阅读代码的每个人都能轻松理解发生的事情.

到目前为止,我提出了:

sumPrice: ->
   (items.map (a) -> a.price * a.quantity).reduce (a, b) -> a + b
Run Code Online (Sandbox Code Playgroud)
  • 包含太多功能魔法
  • 失去描述性

和:

sumPrice: ->
   sum = 0
   for item in items
     sum += item.price * item.quantity
   sum
Run Code Online (Sandbox Code Playgroud)
  • 新手JS /咖啡程序员可以理解
  • 感觉有点愚蠢

我喜欢CoffeeScript,所以我希望有一个更好的解决方案,我想念的这个和类似的场景.

Leo*_*tny 14

功能风格并不是那么糟糕.CoffeeScript允许你像这样美化你的代码:

items
  .map (item) ->
    item.price * item.quantity
  .reduce (x,y) ->
    x+y
Run Code Online (Sandbox Code Playgroud)

此代码比您的单行更容易理解.

如果你不喜欢,map你可以使用for.像这样:

(for item in items
  item.price * item.quantity)
  .reduce (x,y)->x+y
Run Code Online (Sandbox Code Playgroud)

或者像这样:

prods = for item in items
  item.price * item.quantity
prods.reduce (x,y)->x+y
Run Code Online (Sandbox Code Playgroud)

或者您可以sum()为数组添加自己的方法:

Array::sum = -> @reduce (x,y)->x+y
(item.price * item.quantity for item in items).sum()
Run Code Online (Sandbox Code Playgroud)


epi*_*ian 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
Run Code Online (Sandbox Code Playgroud)

请注意,我0作为初始值传递,reduce因此fn为每个数组值调用回调.


如果你不喜欢扩展内置对象,我想如果你提取计算单个数组项在其自己的函数中的总价格的逻辑,你可以优雅地表示总和为一个单独的减少:

itemPrice = (item) -> item.price * item.quantity

sum = items.reduce ((total, item) -> total + itemPrice item), 0
Run Code Online (Sandbox Code Playgroud)


int*_*nt3 8

您可以使用解构来略微简化代码:

sumPrice: ->
    sum = 0
    sum += price * quantity for {price, quantity} in @items
    sum
Run Code Online (Sandbox Code Playgroud)

我认为没有办法摆脱显式初始化sum.虽然Coffeescript的for循环语法倾向于帮助简化本来会使用的代码map(),但它实际上没有任何类似于简化reduce()类型操作的东西,这就是sumPrice这里所做的.

正如在评论中提到的,一个利用这一解决方案拥有一个呼叫reduce()或者sum()是它避免了创建和反复调用函数的开销.

  • 除了可读性之外,我认为这个答案优于功能性的另一个原因是,这可以归结为一个简单的for循环,它在内存上比功能方法更快更好.这对你的情况可能无关紧要,但我个人认为它对我来说更具可读性,这对两个世界来说都是最好的. (3认同)