Filtrar mapa para valores de Ninguno


He buscado un poco, pero aún no he encontrado una buena respuesta sobre cómo filtrar cualquier entrada en un mapa que tenga un valor de Ninguno. Digamos que tengo un mapa como este:

val map = Map[String, Option[Int]]("one" -> Some(1), 
                                   "two" -> Some(2), 
                                   "three" -> None)

Me gustaría terminar devolviendo un mapa con solo el par ("one", Some(1)) y ("two", Some(2)). Entiendo que esto se hace con aplanar cuando se tiene una lista, pero no estoy seguro de cómo lograr el efecto en un mapa sin dividirlo en claves y valores, y luego tratar de volver a unirlos.

Author: KChaloux, 2012-08-08

3 answers

Como cualquier tipo de colección en la scala.a Map tiene el método filter definido y Option tiene el método isDefined, que es true para Some y false para None. Puede filtrar los valores Nonecombinando estos dos:

scala> map.filter(_._2.isDefined)
res4: scala.collection.immutable.Map[String,Option[Int]] = Map(one -> Some(1), two -> Some(2))
 35
Author: drexin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-07 21:34:55

Si está filtrando los valores None, también puede extraer los valores Some al mismo tiempo para terminar con un Map[String,Int]:

scala> map.collect { case (key, Some(value)) => (key, value) }
res0: scala.collection.immutable.Map[String,Int] = Map(one -> 1, two -> 2)
 44
Author: Kristian Domagala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-29 15:31:06

También map.filterKeys( map(_) != None)

O

for( (k,v) <- map if( v!= None)) yield (k,v)

Este enfoque proporciona un método general filterValues que no existe en los mapas.
Echo de menos tal método, porque ninguna de las alternativas es perfecta.

[Actualizado más tarde] Esta es una versión mejor que no hace una búsqueda en cada entrada y todavía se lee razonablemente claramente.

map.filter( {case (x,y)=> y!=None})

 6
Author: ConorR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-16 17:21:39