我对Scala很新,但我想知道解决这个问题的首选方法是什么.假设我有一个项目列表,我想知道检查项目的总数.我可以这样做:
val total = items.filter(_.itemType == CHECK).map(._amount).sum
Run Code Online (Sandbox Code Playgroud)
这将给我我需要的东西,即不可变变量中所有检查的总和.但它看起来像是3次迭代.一旦过滤检查,再次映射金额,然后总和.另一种方法是做一些事情:
var total = new BigDecimal(0)
for (
item <- items
if item.itemType == CHECK
) total += item.amount
Run Code Online (Sandbox Code Playgroud)
这给了我相同的结果,但是1次迭代和一个可变变量看起来也很好.但是,如果我想提取更多信息,比如支票总数,那就需要更多的计数器或可变变量,但我不必再次遍历列表.似乎不是实现我需要的"功能"方式.
var numOfChecks = 0
var total = new BigDecimal(0)
items.foreach { item =>
if (item.itemType == CHECK) {
numOfChecks += 1
total += item.amount
}
}
Run Code Online (Sandbox Code Playgroud)
因此,如果您发现自己需要在列表中使用一堆计数器或总计,则首选保留可变变量或不担心它会执行以下操作:
val checks = items.filter(_.itemType == CHECK)
val total = checks.map(_.amount).sum
return (checks.size, total)
Run Code Online (Sandbox Code Playgroud)
这似乎更容易阅读,只能使用 vals
在一次迭代中解决问题的另一种方法是使用视图或迭代器:
items.iterator.filter(_.itemType == CHECK).map(._amount).sum
Run Code Online (Sandbox Code Playgroud)
要么
items.view.filter(_.itemType == CHECK).map(._amount).sum
Run Code Online (Sandbox Code Playgroud)
这样,表达式的评估被推迟到调用sum.
如果您的项目是案例类,您也可以这样写:
items.iterator collect { case Item(amount, CHECK) => amount } sum
Run Code Online (Sandbox Code Playgroud)
您可以使用foldLeft:
(0 /: items) ((total, item) =>
if(item.itemType == CHECK)
total + item.amount
else
total
)
Run Code Online (Sandbox Code Playgroud)
以下代码将返回一个元组(支票数 - >金额总和):
((0, 0) /: items) ((total, item) =>
if(item.itemType == CHECK)
(total._1 + 1, total._2 + item.amount)
else
total
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
809 次 |
| 最近记录: |