scala – 当将`map`应用于`Set`时,你有时希望结果不是一组而是忽
或者如何在映射Set时避免意外删除重复项?
这是我经常犯的错误.看下面的代码: def countSubelements[A](sl: Set[List[A]]): Int = sl.map(_.size).sum 该函数应计算所有包含列表的累计大小.问题是在将列表映射到它们的长度之后,结果仍然是Set,并且所有大小为1的列表都减少为单个代表. 这只是我有这个问题吗?我能做些什么来防止这种情况发生?我想我喜欢有两种方法mapToSet和mapToSeq for Set.但是没有办法强制执行此操作,有时您不会在本地注意到您正在使用Set. 也许你甚至有可能为Seq编写代码,而另一个类中的某些东西发生了变化,底层对象变成了Set? 也许是最好的做法,不要让这种情况出现? 远程编辑破坏了我的代码 想象一下以下情况: val totalEdges = graph.nodes.map(_.getEdges).map(_.size).sum / 2 您从图形中获取Node对象的集合,使用它们获取它们的相邻边缘并对它们求和.如果graph.nodes返回Seq,则此方法有效. 如果有人决定让Graph将其节点作为Set返回,它就会中断;没有这个代码看起来可疑(至少不是我,你期望每个集合可能最终成为一个集?)并且没有触及它. 解决方法
如果想要一个Seq并得到一个Set,似乎会有很多可能的“陷阱”.方法实现可以依赖于对象的类型和(带有重载)参数,这并不奇怪.使用Scala implicits,该方法甚至可以依赖于预期的返回类型.
防止意外的方法是明确标记类型.例如,使用返回类型注释方法,即使它不是必需的.至少这样,如果graph.nodes的类型从Seq更改为Set,程序员就会意识到存在潜在的破坏. 对于您的具体问题,为什么不定义自己的mapToSeq方法, scala> def mapToSeq[A,B](t: Traversable[A])(f: A => B): Seq[B] = t.map(f)(collection.breakOut) mapToSeq: [A,B](t: Traversable[A])(f: A => B)Seq[B] scala> mapToSeq(Set(Seq(1),Seq(1,2)))(_.sum) res1: Seq[Int] = Vector(1,3) scala> mapToSeq(Seq(Seq(1),2)))(_.sum) res2: Seq[Int] = Vector(1,3) 使用breakOut:CanBuildFrom的优点是从Set到Seq的转换没有额外的开销. 您可以使用pimp my library pattern使mapToSeq看起来是Severs和Set继承的Traversable特征的一部分. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |