Scala vals 与 vars
我对 Scala 还很陌生,但我想知道解决这个问题的首选方法是什么。假设我有一个物品清单,我想知道支票物品的总金额。我可以这样做:
val total = items.filter(_.itemType == CHECK).map(._amount).sum
这会给我我需要的东西,即不可变变量中所有检查的总和。但它似乎需要 3 次迭代才能完成。一次过滤支票,再次映射金额,然后求总和。另一种方法是这样做:
var total = new BigDecimal(0)
for (
item <- items
if item.itemType == CHECK
) total += item.amount
这给了我相同的结果,但有 1 次迭代和一个可变变量,这看起来也很好。但是,如果我想提取更多信息,例如检查总数,则需要更多计数器或可变变量,但我不必再次迭代列表。似乎不是实现我需要的“功能”方式。
var numOfChecks = 0
var total = new BigDecimal(0)
items.foreach { item =>
if (item.itemType == CHECK) {
numOfChecks += 1
total += item.amount
}
}
因此,如果您发现自己需要列表上的一堆计数器或总计,那么最好保留可变变量,还是不担心它,可以执行以下操作:
val checks = items.filter(_.itemType == CHECK)
val total = checks.map(_.amount).sum
return (checks.size, total)
这似乎更易于阅读,并且仅使用 vals
I'm pretty new to Scala but I like to know what is the preferred way of solving this problem. Say I have a list of items and I want to know the total amount of the items that are checks. I could do something like so:
val total = items.filter(_.itemType == CHECK).map(._amount).sum
That would give me what I need, the sum of all checks in a immutable variable. But it does it with what seems like 3 iterations. Once to filter the checks, again to map the amounts and then the sum. Another way would be to do something like:
var total = new BigDecimal(0)
for (
item <- items
if item.itemType == CHECK
) total += item.amount
This gives me the same result but with 1 iteration and a mutable variable which seems fine too. But if I wanted to to extract more information, say the total number of checks, that would require more counters or mutable variables but I wouldn't have to iterate over the list again. Doesn't seem like the "functional" way of achieving what I need.
var numOfChecks = 0
var total = new BigDecimal(0)
items.foreach { item =>
if (item.itemType == CHECK) {
numOfChecks += 1
total += item.amount
}
}
So if you find yourself needing a bunch of counters or totals on a list is it preferred to keep mutable variables or not worry about it do something along the lines of:
val checks = items.filter(_.itemType == CHECK)
val total = checks.map(_.amount).sum
return (checks.size, total)
which seems easier to read and only uses vals
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在一次迭代中解决问题的另一种方法是使用视图或迭代器:
或
这样,表达式的计算会被延迟到调用
sum
为止。如果您的项目是案例类,您也可以这样写:
Another way of solving your problem in one iteration would be to use views or iterators:
or
This way the evaluation of the expression is delayed until the call of
sum
.If your items are case classes you could also write it like this:
我发现说进行“三次迭代”有点误导——毕竟,每次迭代所做的工作都比一次迭代完成的工作要少。因此,并不自动得出迭代 3 次会比迭代一次花费更长的时间。
创建临时对象,现在是一个问题,因为您将占用内存(即使已缓存),这不是单次迭代的情况。在这些情况下,
view
会有所帮助,即使它添加了更多方法调用来完成相同的工作。希望 JVM 能够优化这一点。请参阅 Moritz 的 回答以获取有关视图的更多信息。I find that speaking of doing "three iterations" is a bit misleading -- after all, each iteration does less work than a single iteration with everything. So it doesn't automatically follows that iterating three times will take longer than iterating once.
Creating temporary objects, now that is a concern, because you'll be hitting memory (even if cached), which isn't the case of the single iteration. In those cases,
view
will help, even though it adds more method calls to do the same work. Hopefully, JVM will optimize that away. See Moritz's answer for more information on views.您可以使用
foldLeft
来实现:以下代码将返回一个元组(支票数 -> 金额总和):
You may use
foldLeft
for that:The following code will return a tuple (number of checks -> sum of amounts):