gpt4 book ai didi

scala - 映射 Set 时避免意外删除重复项

转载 作者:行者123 更新时间:2023-12-02 15:45:34 24 4
gpt4 key购买 nike

我真的很喜欢函数式编程概念,但是在映射恰好是 Set 的集合时,我现在在两个不同的场合都遇到了同样的问题。 (即自动删除重复项)。问题是,在转换此类集合的元素后,输出容器也是一个集合,因此会删除转换后的输出的任何重复项。

一个非常简短的 REPL session 来说明该问题:

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

我当然期望总年龄为 18 + 18 + 19 = 55,但因为学生存储在 Set 中,映射后他们的年龄也是如此,因此 18 之一在年龄相加之前 s 就消失了。

在实际代码中,这通常更加阴险且难以发现,特别是如果您编写的实用程序代码只需要 Traversable和/或使用声明返回 Traversable 的方法的输出(其实现恰好是一个 Set)。在我看来,这些情况几乎不可能可靠地发现,除非它们表现为错误。

那么,是否有任何最佳实践可以减少我遇到此问题的风险?难道我想错了map -ping 一般的 Traversable 作为概念性地转换每个元素,而不是依次将转换后的元素添加到某个新集合中?我应该打电话.toStream在绘制之前的所有事情上,如果我想保留这个心理模型?

任何提示/建议将不胜感激。

更新:到目前为止,大多数答案都集中在将重复项包含在总和中的机制上。我对一般情况下编写代码时涉及的实践更感兴趣 - 您是否训练过自己始终调用 toList在调用 map 之前在每个集合上?在调用应用程序中的所有集合的方法之前,您是否会仔细检查它们的具体类?等等

修复已被识别为问题的内容微不足道 - 困难的部分是首先防止这些错误蔓延。

最佳答案

您可能希望使用scalaz foldMap 用于此目的,因为它适用于任何可用的 Foldable 类型类。您的案例中的用法如下所示:

persons foldMap (_.age)

foldMap的签名如下:

trait MA[M[_], A] {
val value: M[A]

def foldMap[B](f: A => B)(implicit f: Foldable[M], m: Monoid[B])
}

所以;只要你有一些集合CC[A],其中CC可以折叠(即遍历),来自A的函数=> B 其中 B 是幺半群,您可以累加结果。

关于scala - 映射 Set 时避免意外删除重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9992307/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com