And*_*yle 30 collections functional-programming scala
我非常喜欢函数式编程概念,但是当我在一个集合中进行映射时Set
(即自动删除重复项),我现在被同一个问题所困在两个不同的场合.问题是在转换这样一个集合的元素之后,输出容器也是一个集合,因此删除了转换输出的任何重复.
一个非常简短的REPL会议来说明这个问题:
scala> case class Person(name: String, age: Int)
defined class Person
scala> val students = Set(Person("Alice", 18), Person("Bob", 18), Person("Charles", 19))
students: scala.collection.immutable.Set[Person] = Set(Person(Alice,18), Person(Bob,18), Person(Charles,19))
scala> val totalAge = (students map (_.age)).sum
totalAge: Int = 37
Run Code Online (Sandbox Code Playgroud)
我当然希望总年龄为18 + 18 + 19 = 55,但因为学生 们存放在a中Set
,所以他们的年龄也是如此,因此其中一个18
在年龄之前消失了.
在实际代码中,这通常更加隐蔽,更难以发现,特别是如果您编写实用程序代码,它只需要Traversable
和/或使用声明返回的方法的输出Traversable
(其实现恰好是Set).在我看来,这些情况几乎不可能被发现,直到/除非它们表现为一个错误.
那么,是否有任何最佳实践可以减少我对这个问题的影响?我是否错误地考虑map
将一般的Traversable概念化地转换为每个元素,而不是将转换后的元素依次添加到一些新的集合中?.toStream
如果我想保留这个心理模型,我应该在映射之前调用所有内容吗?
任何提示/建议将不胜感激.
更新:到目前为止,大多数答案都集中在将总和中包含重复项的机制上.在一般情况下编写代码时,我对所涉及的实践更感兴趣 - 你是否自己在调用之前总是调用toList
每个集合map
?在调用方法之前,您是否经常检查应用程序中所有集合的具体类?等等.
修复已经被识别为问题的东西是微不足道的 - 困难的部分是防止这些错误首先蔓延.
oxb*_*kes 19
您可能希望将scalaz foldMap
用于此目的,因为它适用于任何有Foldable
类型类可用的东西.您案例中的用法如下所示:
persons foldMap (_.age)
Run Code Online (Sandbox Code Playgroud)
签名foldMap
如下:
trait MA[M[_], A] {
val value: M[A]
def foldMap[B](f: A => B)(implicit f: Foldable[M], m: Monoid[B])
}
Run Code Online (Sandbox Code Playgroud)
所以; 只要你有一定的收藏CC[A]
哪里CC
可以折叠起来(即穿越),从功能A => B
,其中B为幺,你可以积累的结果.
Vik*_*ang 11
不要将额外的依赖项拖到图片中:
(0 /: students) { case (sum, s) => sum + s.age }
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
667 次 |
最近记录: |