combine condition inside flat map and return resul

2019-08-20 04:43发布

问题:

val date2 = Option(LocalDate.parse("2017-02-01"))
//date1.compareTo(date2)>=0

case class dummy(val prop:Seq[Test])
case class Test(val s :String)
case class Result(val s :String)

  val s = "11,22,33"
  val t = Test(s)
  val dt =Test("2017-02-06")
  val list = dummy(Seq(t))
  val list2 = dummy(Seq(dt))
  val code = Option("22")


      val f = date2.flatMap(c => list2
                                  .prop
                                  .find(d=>LocalDate.parse(d.s)
                                  .compareTo(c)>=0))
                           .map(_ => Result("Found"))
                           .getOrElse(Result("Not Found"))

      code.flatMap(c => list
                         .prop
                         .find(_.s.split(",").contains(c)))
                  .map(_ => Result("Found"))
                  .getOrElse(Result("Not Found"))

I want to && the conditions below and return Result("Found")/Result("Not Found")

  1. d=>LocalDate.parse(d.s).compareTo(c)>=0)
  2. _.s.split(",").contains(c)

Is there any possible way to achieve the above .In actual scenerio list and list 2 are Future

回答1:

I tried to make a more realistic example based on Futures. Here is how I would do it:

val date2 = Option(LocalDate.parse("2017-02-01"))

case class Test(s: String)
case class Result(s: String)

val t = Test("11,22,33")
val dt = Test("2017-02-06")
val code = Option("22")

val f1 = Future(Seq(t))
val f2 = Future(Seq(dt))

// Wait for both futures to finish
val futureResult = Future.sequence(Seq(f1, f2)).map {
  case Seq(s1, s2) =>

    // Check the first part, this will be a Boolean
    val firstPart = code.nonEmpty && s1.exists(_.s.split(",").contains(code.get))

    // Check the second part, also a boolean
    val secondPart = date2.nonEmpty && s2.exists(d => LocalDate.parse(d.s).compareTo(date2.get) >= 0)

    // Do the AND logic you wanted
    if (firstPart && secondPart) {
      Result("Found")
    } else {
      Result("Not Found")
    }
}

// This is just for testing to see we got the correct result
val result = Await.result(futureResult, Duration.Inf)
println(result)

As an aside, your code and date2 values in your example are Options... If this is true in your production code, then we should do a check first to see if they are both defined. If they are not then there would be no need to continue with the rest of the code:

val futureResult = if (date2.isEmpty || code.isEmpty) {
  Future.successful(Result("Not Found"))
} else {
  Future.sequence(Seq(f1, f2)).map {
    case Seq(s1, s2) =>

      val firstPart = s1.exists(_.s.split(",").contains(code.get))
      val secondPart = s2.exists(d => LocalDate.parse(d.s).compareTo(date2.get) >= 0)

      if (firstPart && secondPart) {
        Result("Found")
      } else {
        Result("Not Found")
      }
  }
}


回答2:

Use pattern matching on Option instead of using flatMap

e.g.

val x = Some("20")
x match {
  case Some(i) => println(i) //do whatever you want to do with the value. And then return result
  case None => Result("Not Found")
}

Looking at what you are trying to do, You would have to use pattern matching twice, that too nested one.



标签: scala