2010-09-06 15 views
29

Tengo un HashMap mutable y me gustaría utilizarlo como un diccionario predeterminado. El método obvio parece ser usar getOrElse y proporcionar el valor predeterminado cada vez como un segundo valor. Sin embargo, esto parece un poco poco elegante en mi caso de uso ya que el valor predeterminado no cambia.Scala: Uso de HashMap con un valor predeterminado

var x = HashMap(1 -> "b", 2 -> "a", 3 -> "c") 

println(x.getOrElse(4, "_") 
println(x.getOrElse(5, "_")) 
// And so on... 
println(x.getOrElse(10, "_")) 

¿Hay alguna manera de crear un HashMap (o clase similar) de tal manera que el intento de acceso a claves definidas devuelve un valor predeterminado establecido en la creación de la HashMap? Me he dado cuenta de que HashMap.default se acaba de establecer a lanzar una excepción, pero me pregunto si esto se puede cambiar ...

+5

Para cualquier persona que se topa con esta pregunta, el post de missingfaktor afirma correctamente que "Scala 2.9.1 mutable.Map viene con un método withDefaultValue." – wynnch

Respuesta

34

Prueba esto:

import collection.mutable.HashMap 
val x = new HashMap[Int,String]() { override def default(key:Int) = "-" } 
x += (1 -> "b", 2 -> "a", 3 -> "c") 

continuación:

scala> x(1) 
res7: String = b 

scala> x(2) 
res8: String = a 

scala> x(3) 
res9: String = c 

scala> x(4) 
res10: String = - 
+4

+1. Me pregunto por qué 'mutable.HashMap' no proporciona un método' withDefaultValue' como 'inmutable.HashMap'. – missingfaktor

+2

Es una sintaxis horrible, pero funciona. Tal vez la falta de withDefaultValue para HashMaps mutable se debe informar como un error? –

+4

Hay un "!!! todo: pasar a mapas generales?" comente en el vecino 'withDefault' en http://www.scala-lang.org/api/current/scala/collection/immutable/Map.html. Entonces puede ser que esto no sea demasiado exagerado.La lista de correo de scala-user es probablemente un buen lugar para preguntar acerca de esto y ver si se debe informar un error. – huynhjl

1
scala> val x = HashMap(1 -> "b", 2 -> "a", 3 -> "c").withDefaultValue("-") 
x: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,b), (2,a), (3,c)) 

scala> x(3) 
res0: java.lang.String = c 

scala> x(5) 
res1: java.lang.String = - 

EDIT:

Para mutable.HashMap, se puede hacer lo siguiente:

scala> import collection.mutable 
import collection.mutable 

scala> val x = new mutable.HashMap[Int, String] { 
    | override def apply(key: Int) = super.get(key) getOrElse "-" 
    | } 
x: scala.collection.mutable.HashMap[Int,String] = Map() 

scala> x += (1 -> "a", 2 -> "b", 3 -> "c") 
res9: x.type = Map((2,b), (1,a), (3,c)) 

scala> x(2) 
res10: String = b 

scala> x(4) 
res11: String = - 

Puede haber una forma mejor de hacerlo. Espera a que otros respondan.

+0

Eso sólo parece funcionar con HashMaps inmutables. –

+1

@PythonPower: No había especificado en su pregunta original que estaba usando 'mutable.HashMap'. No sé cómo hacerlo con 'mutable.HashMap'. Tendré que mirar en la API. – missingfaktor

+0

Sí, lo siento, no especifiqué: he editado mi pregunta para dejarlo en claro ahora. –

0

soy más un tipo java ... pero si getOrElse no es definitiva, ¿por qué no sólo extiendo HasMap y proporcionar algo como esto:

override def getOrElse(k: Int, default: String) = { 
    return super.getOrElse(k,"_") 
} 

Nota: La sintaxis es probablemente jodido, pero esperemos que obtendrá el punto

+0

Sí, creo que es posible ampliar HashMap. En ese caso, probablemente sería más fácil cambiar el método HashMap.default para devolver lo que quiero. El constructor podría tomar el valor predeterminado y el método HashMap.default simplemente lo devolvería. Sin embargo, espero que haya un método más fácil. –

+0

No hacemos esto porque es más complicado que 'getOrElse' - tiene menos flexibilidad, es innecesariamente detallado, y si * debes * hacer esto, es una fuerte indicación de que deberías estar usando una abstracción de alto nivel, como monoides . – BAR

67

Vaya, he visitado este hilo exactamente un año después de haber publicado mi última respuesta aquí. :-)

Scala 2.9.1. mutable.Map viene con un método withDefaultValue. REPL sesión:

scala> import collection.mutable 
import collection.mutable 

scala> mutable.Map[Int, String]().withDefaultValue("") 
res18: scala.collection.mutable.Map[Int,String] = Map() 

scala> res18(3) 
res19: String = "" 
+0

Esto debe marcarse como la respuesta correcta –

+0

. Me preocupa el rendimiento de esto. ¿Mutable.Map usa HashMaps? ¿Cómo es su rendimiento? –

Cuestiones relacionadas