blue-sky
blue-sky

Reputation: 53806

How to filter remove None types from List[(String , Option[Int])]?

Here I'm attempting to remove None type from a list of (String , Option[Int]) where the None type can be at position 2 in the tuple :

val l : List[(String , Option[Int])] = List(
         ("a" , None),
         ("b" , Option(1)),
         ("c" , Option(2))
    )

val filteredSomes = for { 
    (e <- l)
        if(e._2 >= 0)
} yield e

println(filteredSomes);

But this does not compile :

causes error :

 ')' expected but '<-' found.
[error]                 (e <- l)
[error]                    ^

Can flatten be used against this collection instead of for each ?

Upvotes: 2

Views: 4484

Answers (4)

corvus_192
corvus_192

Reputation: 422

Another option is to use collect

List(
  ("a" , None),
  ("b" , Option(1)),
  ("c" , Option(2)),
  ("d",  Option(-1))
) collect {case t @ (_, Some(i)) if i >= 0 => t}
//result: List((b,Some(1)), (c,Some(2)))

Upvotes: 1

Tyler
Tyler

Reputation: 18177

You can accomplish the same thing by using a filter with some pattern matching:

val filteredSomes = l.filter {

    // This is the only case that you want to pass your filter.
    // We are pattern matching the tuple and saying that we don't 
    // care about the String's value but we want the Option[Int] 
    // to be defined and be greater-than-or-equal to zero
    case (_, Some(i)) if i >= 0 => true 

    // Any other case should not pass the filter
    case _ => false 
}

Here is an example from the Scala REPL

scala> val l : List[(String , Option[Int])] = List(("a" , None), ("b" , Option(1)), ("c" , Option(2)))
l: List[(String, Option[Int])] = List((a,None), (b,Some(1)), (c,Some(2)))

scala> l.filter { 
     |     case (_, Some(i)) if i >= 0 => true
     |     case _ => false
     | }
res6: List[(String, Option[Int])] = List((b,Some(1)), (c,Some(2)))

Upvotes: 2

rleibman
rleibman

Reputation: 247

Similar to the cheseaux's answer, but more idiomatic:

l.filter(_._2.isDefined)

Upvotes: 9

cheseaux
cheseaux

Reputation: 5315

Why not simply

l.filter(_._2 != None)

Or if you really want to express it using the for comprehensions form, you can do it like this

for(e <- l; if (e._2 != None)) yield e

Upvotes: 2

Related Questions