Scala:使用flatMap设置的列表

Evg*_*kov 1 collections scala

我有类型字段的类Set[String].另外,我有这个类的对象列表.我想将所有这些对象集中的所有字符串收集到一个集合中.我已经可以这样做了:

case class MyClass(field: Set[String])

val list = List(
  MyClass(Set("123")),
  MyClass(Set("456", "798")),
  MyClass(Set("123", "798"))
)

list.flatMap(_.field).toSet // Set(123, 456, 798)
Run Code Online (Sandbox Code Playgroud)

它有效,但我认为,我可以只使用它flatMap,而不需要toSet调用.我试过这个,但它给出了编译错误:

// error: Cannot construct a collection of type Set[String]
// with elements of type String based on a collection of type List[MyClass].
list.flatMap[String, Set[String]](_.field)
Run Code Online (Sandbox Code Playgroud)

如果我将类型更改listSet(即val list = Set(...)),则此类flatMap调用有效.

所以,我可以用某种方式Set.canBuildFrom或任何其他CanBuildFrom对象调用flatMapList对象,所以,我会得到Set的结果呢?

Ole*_*cov 5

CanBuildFrom您想要的实例被调用breakOut,并且必须作为第二个参数提供:

import scala.collection.breakOut

case class MyClass(field: Set[String])

val list = List(
  MyClass(Set("123")),
  MyClass(Set("456", "798")),
  MyClass(Set("123", "798"))
)

val s: Set[String] = list.flatMap(_.field)(breakOut)
Run Code Online (Sandbox Code Playgroud)

请注意,变量的显式类型注释s是必需的 - 这就是选择类型的方式.

编辑:

如果您正在使用Scalazcats,您也可以使用foldMap:

import scalaz._, Scalaz._
list.foldMap(_.field)
Run Code Online (Sandbox Code Playgroud)

这实质上是做什么mdm的回答提出,除了Set.empty++部分在已经出炉.