微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将 Scala Iterable[T] 转换为 Option[Iterable[S]],如果所有 T 都是 S 的实例,则填充?

如何解决将 Scala Iterable[T] 转换为 Option[Iterable[S]],如果所有 T 都是 S 的实例,则填充?

我有一种模糊的感觉,这样的方法可能存在(可能在 Cats 中?) - 目的是将 Iterable[T]Set[T] 'm 实际上对) 感兴趣到 Option[Iterable[S]] - 结果是:

  • Some[Iterable[S]] :如果 Iterable[T] 中的所有条目都是 S
  • 的实例
  • None :如果 Iterable[T] 中的任何条目不是 S 的实例

我知道 Cats 中已经有一种类似的方法,由 Alternative 授予 - 它是 separate

import cats.implicits._
import alleycats.std.set._

val stringsAndInts: Set[Either[String,Int]] = Set(Right(6),Left("Foo"))
val (strings: Set[String],ints: Set[Int]) = stringsAndInts.separate

...这对 Set[Either[A,B] 很有效 - 但对于这个问题,我只对任何旧的 Set[T] 感兴趣。

collect 怎么样?

这段使用 Scala 标准库方法 collect代码将编译 - 但请注意,它总是会产生一个 Set[S] - 即使某些 setofT 不是 {{ 1}}:

S

解决方法

考虑不定形类型安全转换

import shapeless._
import syntax.typeable._

val xs: Set[Any] = Set("picard","worf")

xs.cast[Set[Int]]
// res1: Option[Set[Int]] = None

xs.cast[Set[String]]
// res2: Option[Set[String]] = Some(value = Set("picard","worf"))

如果您希望获得与 collect 类似的功能并且已经在类路径上有猫,那么这里是单行

import alleycats.std.set._
animals.map(implicitly[ClassTag[Dog]].unapply).sequence

Option[Set[Dog]] 的类型。

,

正如 Luis Miguel Mejía Suárez 在评论中指出的那样,由于类型擦除,我想要的方法不可能用于任意类型。

最后,我写了这样的代码:

val animals: Set[Animal] = ???
val optDogs: Option[Set[Dog]] = animals.foldLeft(Option(Set.empty[Dog])) {
  case (oDogs,dog: Dog) => oDogs.map(_ + dog)
  case _ => None
}

...不过很高兴看到更好的实现!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。