eranga
eranga

Reputation: 557

Filter two Future[Seq] with for comprehension scala

I have some functions which returns list of tuple elements(Int, Int) with future. For simplicity I will define two futures

  val f1 = Future {
    List((8, 3), (2, 1), (4, 2), (3, 4))
  }
  val f2 = Future {
    List((2, 3), (5, 1), (7, 9))
  }

I want to filter and get the elements form these two future lists with below criteria.

Tuples which contains same element in second position

In this scenario output should be

List(((2,1),(5,1)), ((8,3),(2,3))) 

I can do this with normal lists(without futures) with for comprehension like below

val l1 = List((4, 2), (3, 4), (2, 1), (8, 3))
val l2 = List((2, 3), (5, 1), (7, 9))

val o = for {
  a <- l1
  b <- l2 if a._2 == b._2
} yield (a, b)

How to do it with futures?

Upvotes: 0

Views: 785

Answers (3)

Viktor Klang
Viktor Klang

Reputation: 26579

Scala 2.12 adds a zipWith to Future:

f1.zipWith(f2) {
  (l1, l2) => for {
    a <- l1
    b <- l2 if a._2 == b._2
  } yield (a, b)
}

For more information, see this blog post: http://viktorklang.com/blog/Futures-in-Scala-2.12-part-2.html

Upvotes: 1

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149518

Another possibility would be the ListT monad transformer from scalaz (although it violates the associative law):

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Await, Future}
import scalaz.Scalaz._
import scalaz._
import scala.concurrent.duration._

def main(args: Array[String]): Unit = {
  val f1 = Future {
    List((8, 3), (2, 1), (4, 2), (3, 4))
  }

  val f2 = Future {
    List((2, 3), (5, 1), (7, 9))
  }

  val first = ListT[Future, (Int, Int)](f1)
  val second = ListT[Future, (Int, Int)](f2)

  val res = for {
    a <- first
    b <- second if a._2 == b._2
  } yield (a, b)

  println(Await.result(res.run, 3 seconds))
}

Upvotes: 1

Kamil Banaszczyk
Kamil Banaszczyk

Reputation: 1153

Additional solution if you want to use full for comprehension:

val o2 = for {
  l1 <- f1
  l2 <- f2
} yield for {
  a <- l1
  b <- l2 if a._2 == b._2
} yield (a,b)

Of course you will have Future here, so you need to await for result or pass it further to something which will process it

Upvotes: 3

Related Questions