Scala flatmap Seq

时间:2018-03-20 23:31:05

标签: scala

我有一个数组:选项[Seq [People]]

case class People (
   name: Option[String],
   tall: Option[Boolean],
   fat: Boolean
)

我想要的是:

String name = "Jack|Tom|Sam"
String tall = "True|True|True"
String fat = "True|False|True"

所以,我试过了:

name = array.flatMap(x => x.name).map(_.mkString("|"))
name = array.flatMap(_.slot_name).map(_.mkString("|"))

上述尝试无效。

3 个答案:

答案 0 :(得分:2)

这是您需要的(在 Scala REPL 会话中演示):

$ scala
Welcome to Scala 2.12.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_161).
Type in expressions for evaluation. Or try :help.

scala> case class People (
     |    name: Option[String],
     |    tall: Option[Boolean],
     |    fat: Boolean
     | )
defined class People

scala> val array = Option(
     |   Seq(
     |     People(Some("Jack"), Some(true), true),
     |     People(Some("Tom"), Some(true), false),
     |     People(Some("Sam"), Some(true), true),
     |   )
     | )
array: Option[Seq[People]] = Some(List(People(Some(Jack),Some(true),true), People(Some(Tom),Some(true),false), People(Some(Sam),Some(true),true)))

scala> val name = array.fold("")(_.flatMap(_.name).mkString("|"))
name: String = Jack|Tom|Sam

scala> val tall = array.fold("")(_.flatMap(_.tall).map(_.toString.capitalize).mkString("|"))
tall: String = True|True|True

scala> val fat = array.fold("")(_.map(_.fat.toString.capitalize).mkString("|"))
fat: String = True|False|True

每个fold操作都认为array的值可能是None(第一个参数列表,它映射到一个空字符串);否则,fold采用定义的序列(在第二个参数列表中),然后处理每个成员。

flatMap个操作将People个实例转换为相应的必需可选值(nametall),检索定义的值,同时过滤掉未定义的值。 (flatMap相当于map后跟flatten。)由于fat字段不是可选字段,因此只需要map,而不是{{} 1}}。

必须通过另一个flatMap操作将生成的Boolean值转换为大写字符串,以匹配您所需的输出。 (如果是map,则可以与将fat个实例转换为map值的People调用相结合。)

最后,使用virgule(" |")作为分隔符将结果Boolean加入到单个Seq[String] 通过String函数。

答案 1 :(得分:0)

mkStringSeq[String]

的方法
val names = array.map(_.flatMap(x => x.name).mkString("|")).getOrElse("")
val tall = array.map(_.flatMap(_.tall).map(_.toString.capitalize).mkString("|")).getOrElse("")
val fat = array.map(_.map(_.fat.toString.capitalize).mkString("|")).getOrElse("")

答案 2 :(得分:0)

以下是使用collect而非array元素的另一种方法

val array = Seq(
    People(Some("Jack"), Some(true), true),
    People(Some("Tom"), Some(true), false),
    People(Some("Sam"), Some(true), true)
)
array: Seq[People] = List(People(Some(Jack),Some(true),true), People(Some(Tom),Some(true),false), People(Some(Sam),Some(true),true))

获取所有人的姓名

scala> val name = array.collect{
  case p : People => p.name
}.flatten.mkString("|")
    res3: name: String = Jack|Tom|Sam

让所有人都高高在上

scala> val tall = array.collect{
  case p: People => p.tall
}.flatten.mkString("|")
 tall: String = true|true|true

同样的脂肪

scala> val tall = array.collect{
  case p: People => p.fat.toString.capitalize
}.mkString("|")
tall: String = True|False|True