J'essaie de construire des cartes imbriquées dans Scala, où la carte extérieure et intérieure utilise la méthode "withDefaultValue". Par exemple, les éléments suivants: de sorte que la carte, lorsqu'elle est adressée par les touches appropriées, me donne ce que j'ai mis en place. Cependant, la carte elle-même apparaît vide! Même M.Size retourne 0 dans cet exemple. Quelqu'un peut-il expliquer ce qui se passe ici? P> p>
5 Réponses :
withDefaultValue code> est utilisé pour renvoyer une valeur lorsque la clé n'a pas été trouvée. Il ne peuplie pas la carte. Donc, vous mappez de rester vide. Un peu comme en utilisant
getorelse (a, b) code> où
b code> est fourni par
withdefaulardvalue code>. P>.
Bien sûr, mais quand j'appelle m (1) (2) = 5, cela devrait placer la valeur 5 sur la carte. Pourquoi, alors la carte apparaît-elle vide après cette "mise à jour ()"?
@nomad, je suis assez intrigué par le comportement intéressant ici, mais tout fait en réalité beaucoup de sens. m est b> toujours vide après cette mise à jour, car ce que vous avez mis à jour était pas b> m; Vous avez mis à jour une des valeurs par défaut de M. C'est-à-dire que vous avez mis à jour la carte qui est référencée par m (1) jusqu'à ce que m (1) ait une valeur réelle. Puisque vous avez changé la taille de que B> carte, et que vous n'avez jamais mis à jour les paires de la valeur de clé m> m> m> m> m est toujours vide, dans la mesure où elle est concernée.
Ce que vous voyez est l'effet que vous avez créé une seule carte carte [int, int] code> Il s'agit de la valeur par défaut lorsque la touche ne figure pas dans la carte extérieure.
scala> val m = HashMap.empty[(Int, Int), Int].withDefaultValue(3)
m: scala.collection.mutable.Map[(Int, Int),Int] = Map()
scala> m((1, 2))
res0: Int = 3
scala> m((1, 2)) = 5
scala> m((1, 2))
res3: Int = 5
scala> m
res4: scala.collection.mutable.Map[(Int, Int),Int] = Map((1,2) -> 5)
Ce n'est certainement pas un bug. p>
Le comportement de Regardons de près ce qui se passe. Il sera plus facile de comprendre si nous tirons la carte par défaut comme une variable distincte afin que nous puissions inspecter est à volonté; Appelons-le donc maintenant chaque fois que remarque que c'est Voyons donc ce qui se passe: p> withDefaultValue code> est de stocker une valeur par défaut (dans votre cas, une carte mutable) à l'intérieur de la carte à renvoyer dans le cas où elles ne existent pas. Ce n'est pas la même chose qu'une valeur insérée em> dans la carte lorsqu'elle est introuvable. P>
défaut code> p>
par défaut code> est une carte mutable (qui a sa propre valeur par défaut). Maintenant, nous pouvons créer
m code> et donner
par défaut code> comme valeur par défaut. P>
m Code> est accessible avec une clé manquante, il retournera
par défaut code>. Notez que c'est le même comportement que vous avez exactement que vous avez parce que
withdefaulardValue code> est défini comme suit: p>
D: B code> et non
d: => b code>, il ne créera donc pas une nouvelle carte chaque fois que la valeur par défaut est accessible; Il retournera le même objet exact, ce que nous avons appelé
par défaut code>. p>
m2 // Map(1 -> Map(2 -> 6))
Je l'obtiens maintenant; La ventilation a beaucoup aidé. C'est intéressant à quel point mon préjugé initial sur la façon dont je pensais que la fonction devrait i> me empêcher de voir ce qui se passait réellement.
J'avais juste exactement le même problème et je suis heureux de trouver la réponse de DHG. Depuis la frappe GetorelseUpdate tout le temps n'est pas très concis, j'ai proposé cette petite extension de l'idée que je veux partager: Vous pouvez déclarer une classe qui utilise getorelseeupdate comme comportement par défaut pour l'opérateur ():
var map = new DefaultDict[Int, DefaultDict[Int, Int]]( key => new DefaultDict(key => 3)) map(1)(2) = 5
S'il vous plaît ne faites pas. Merci.
Je sais que c'est un peu tard mais je viens de voir le poste pendant que j'essayais de résoudre le même problème.
L'API est probablement différente de la version 2012, mais vous pouvez utiliser withdefault code> à la place que
withdefaultValue code>.
La différence est que withdefault code> prend une fonction en tant que paramètre, qui est exécuté chaque fois qu'une clé manquée est demandée;) p>