2010-09-06 10 views
29

Ich habe eine veränderbare HashMap und möchte es wie ein Standard-Wörterbuch verwenden. Die offensichtliche Methode scheint zu sein, getOrElse zu verwenden und den Standardwert jedes Mal als einen zweiten Wert zur Verfügung zu stellen. Dies scheint jedoch in meinem Anwendungsfall etwas unelegant zu sein, da sich der Standardwert nicht ändert.Scala: Verwenden von HashMap mit einem Standardwert

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

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

Gibt es eine Möglichkeit, eine HashMap (oder Klasse) so zu erstellen, dass nicht definierte Schlüssel für den Zugriff versucht, einen Standardwert zurück gesetzt auf der Schaffung des HashMap? Ich bemerke, dass HashMap.default wird nur gesetzt, eine Ausnahme zu werfen, aber ich frage mich, ob dies geändert werden kann ...

+5

Für jeden, der auf diese Frage stolpert, missingfaktor der Post heißt es richtig, dass „Scala 2.9.1 mutable.Map kommt mit einem withDefaultValue Methode.“ – wynnch

Antwort

34

Versuchen Sie folgendes:

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

Dann:

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. Ich frage mich, warum 'mutable.HashMap' keine' withDefaultValue' Methode wie 'immutable.HashMap' anbietet. – missingfaktor

+2

Es ist schrecklich Syntax, aber es macht den Trick. Vielleicht sollte das Fehlen von withDefaultValue für veränderbare HashMaps als Fehler gemeldet werden? –

+4

Es gibt ein "!!! Todo: zu allgemeinen Karten bewegen?" Kommentar im benachbarten 'withDefault' in http://www.scala-lang.org/api/current/scala/collection/immutable/Map.html. Also vielleicht ist das nicht zu weit weg.Die scala-user-Mailingliste ist wahrscheinlich ein guter Ort, um sich darüber zu erkundigen und zu sehen, ob ein Fehler gemeldet werden sollte. – 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:

Für mutable.HashMap, Sie Folgendes tun können:

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 = - 

Möglicherweise gibt es einen besseren Weg, dies zu tun. Warten Sie, bis andere antworten.

+0

Das erscheint nur mit unveränderlichen HashMaps zu arbeiten. –

+1

@PythonPower: Sie hatten es nicht in Ihrer ursprünglichen Frage angegeben, dass Sie 'mutable.HashMap' verwendet haben. Ich weiß nicht, wie man es mit 'mutable.HashMap' macht. Ich muss in die API schauen. – missingfaktor

+0

Ja, tut mir leid, ich habe nicht angegeben - Ich habe meine Frage bearbeitet, um es jetzt klarzustellen. –

0

Ich bin eher ein Java-Kerl ... aber wenn getOrElse nicht endgültig ist, warum Sie nicht nur HasMap erweitern und so etwas wie dieses bieten:

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

Hinweis: Syntax wird wahrscheinlich vermasselt aber hoffentlich werden Sie erhalten den Punkt

+0

Ja, ich denke, es ist möglich, HashMap zu erweitern. In diesem Fall wäre es wahrscheinlich einfacher, die HashMap.default-Methode zu ändern, um das zurückzugeben, was ich möchte. Der Konstruktor könnte den Standardwert annehmen und die HashMap.default-Methode würde dies einfach zurückgeben. Ich hoffe aber, dass es eine einfachere Methode gibt. –

+0

Wir machen das nicht bc es ist komplizierter als 'getOrElse' - es hat weniger Flexibilität, ist unnötig ausführlich, und wenn Sie * dies * tun müssen, ist ein starkes Anzeichen, dass Sie eine Abstraktion auf hohem Niveau, wie Monoiden, verwenden sollten . – BAR

67

Wow, ich habe diesen Thread genau ein Jahr nach meiner letzten Antwort hier besucht. :-)

Scala 2.9.1. mutable.Map kommt mit einer withDefaultValue Methode. ERSATZ-Sitzung:

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

Dies sollte als die richtige Antwort markiert werden –

+0

Ich bin besorgt über die Leistung für diese - tut mutable.Map HashMaps verwenden? Wie ist seine Leistung? –

Verwandte Themen