简体   繁体   中英

Scala flatmap Seq

I have an array: Option[Seq[People]]

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

What I want looks like:

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

So, I tried:

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

The above tries didn't work.

Here's what you need (demonstrated in a Scala REPL session):

$ 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

Each fold operation considers that the value of array may be None (the first argument list, which it maps to an empty string); otherwise, fold takes the defined sequence (in the second argument list) then processes each member.

The flatMap operations convert People instances to the corresponding required optional values ( name and tall ), retrieving the defined values while filtering out those that are undefined. ( flatMap is equivalent to a map followed by flatten .) Since the fat field is not optional, only a map is required, instead of flatMap .

Resulting Boolean values must be converted into capitalized strings through another map operation, in order to match your required output. (In the case of fat , this can be combined with the map call that converts People instances to a Boolean value.)

Finally, the resulting Seq[String] 's are joined into a single String using the virgule ("|") as a separator via the mkString function.

The mkString is a method of Seq[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("")

Here is another approach using collect over an array of elements

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))

For getting name(s) of all people

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

For getting all tall(s) of people

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

Same way for fat(s)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM