scala - redes - informacion mediatica
Cómo implementar Map con la operación predeterminada en Scala (5)
¿Por qué no usar withDefaultValue (value)?
scala> val m = Map[Int, List[String]]().withDefaultValue(List())
m: scala.collection.immutable.Map[Int,List[String]] = Map()
scala> m(123)
res1: List[String] = List()
class DefaultListMap[A, B <: List[B]] extends HashMap[A, B] {
override def default(key: A) = List[B]()
}
Quiero crear el mapa A -> List[B]
. En mi caso, es Long -> List[String]
pero cuando obtengo una clave del mapa que no tiene valor, me gustaría crear una List
vacía en lugar de una Exception
. Probé diferentes combinaciones, pero no sé cómo hacer que el código pase el compilador.
Gracias por adelantado.
¿Por qué quieres manipular un mapa cuando ya tiene un método para esto?
val m = Map(1L->List("a","b"), 3L->List("x","y","z"))
println(m.getOrElse(1L, List("c"))) //--> List(a, b)
println(m.getOrElse(2L, List("y"))) //--> List(y)
En lugar de utilizar apply
para acceder al mapa, siempre get
usar get
, que devuelve la Option[V]
y luego getOrElse
:
map.get(k) getOrElse Nil
Una gran característica de la biblioteca de programación funcional de Scalaz es el operador unario ~
, que significa "o cero", siempre que el tipo de valor tenga un "cero" definido (qué List
hace, siendo el cero Nil
por supuesto). Entonces el código se convierte en:
~map.get(k)
Esto es doblemente útil porque la misma sintaxis funciona donde (por ejemplo) sus valores son Int
, Double
, etc. (cualquier cosa para la que haya una clase de tipo Zero
).
Ha habido un gran debate en la lista de correo de Map.withDefault
sobre el uso de Map.withDefault
debido a cómo se comporta con el método isDefinedAt
, entre otros. Por esta razón, tiendo a evitarlo.
Hay un método con withDefaultValue
en Map
:
scala> val myMap = Map(1 -> List(10), 2 -> List(20, 200)).withDefaultValue(Nil)
myMap: scala.collection.immutable.Map[Int,List[Int]] = Map((1,List(10)), (2,List(20, 200)))
scala> myMap(2)
res0: List[Int] = List(20, 200)
scala> myMap(3)
res1: List[Int] = List()
withDefault también se puede usar.
/** The same map with a given default function.
* Note: `get`, `contains`, `iterator`, `keys`, etc are not affected
* by `withDefault`.
*
* Invoking transformer methods (e.g. `map`) will not preserve the default value.
*
* @param d the function mapping keys to values, used for non-present keys
* @return a wrapper of the map with a default value
*/
def withDefault[B1 >: B](d: A => B1): immutable.Map[A, B1]
Ejemplo:
scala> def intToString(i: Int) = s"Integer $i"
intToString: (i: Int)String
scala> val x = Map[Int, String]().withDefault(intToString)
x: scala.collection.immutable.Map[Int,String] = Map()
scala> x(1)
res5: String = Integer 1
scala> x(2)
res6: String = Integer 2
Espero que esto ayude.