2012-08-07 19 views
31

He buscado un poco, pero todavía no he encontrado una buena respuesta sobre cómo filtrar las entradas en un mapa que tienen un valor de Ninguno. Decir que tengo un mapa de esta manera:Mapa de filtro para los valores de Ninguno

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

Me gustaría terminar volviendo un mapa con sólo el ("one", Some(1)) y ("two", Some(2)) par. Entiendo que esto se hace con aplanar cuando 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.

Respuesta

34

Como cada tipo de colección en el espacio de nombres scala.collection un 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 None mediante la combinación de estos dos:

scala> map.filter(_._2.isDefined) 
res4: scala.collection.immutable.Map[String,Option[Int]] = Map(one -> Some(1), two -> Some(2)) 
+0

Neato. Aunque no habría adivinado la sintaxis. Todavía estoy un poco confundido con '_. Por lo que entiendo, ¿estamos diciendo que vaya al segundo elemento (el valor) del primer par (actual)? – KChaloux

+2

@KChaloux En este caso '_' se refiere al primer argumento de un literal de función que se pasa al método' filter'. Es una abreviatura de 'x => x._2.isDefined' –

+0

Y el _2 proviene de [Tuple] (http://www.scala-lang.org/api/current/index.html#scala.Tuple2). – fracz

41

Si está filtrando None valores, que también podría extraer los valores de 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) 
+0

Muy bueno, me aseguraré de verificarlo. – KChaloux

+1

Creo que puedes salir sin el toMap :-) –

6

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

o

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

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

[Actualizado más tarde] Esta es una versión mejorada que no realiza una búsqueda en cada entrada y todavía se puede leer con bastante claridad.

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

Cuestiones relacionadas