2012-08-07 12 views
31

Ich habe ein wenig gesucht, aber noch keine gute Antwort darauf gefunden, wie Einträge in eine Map mit dem Wert None herausgefiltert werden können. Sagen, dass ich eine Karte wie diese:Filterkarte für Werte von None

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

Ich mag würde eine Karte Rückkehr nur mit dem ("one", Some(1)) und ("two", Some(2)) Paar am Ende. Ich verstehe, dass dies mit flatten gemacht wird, wenn Sie eine Liste haben, aber ich bin mir nicht sicher, wie ich den Effekt auf einer Karte erreichen kann, ohne sie in Schlüssel und Werte aufzuteilen und dann wiederzuvereinigen.

Antwort

34

Wie jeder Kollektionstyp in dem Namensraum scala.collection a Map hat die filter Methode definiert und hat die OptionisDefined Methode, die für Sometrue und false für None ist. Sie können die None Werte herauszufiltern durch die Kombination dieser beiden:

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

Neato. Ich hätte die Syntax nicht erraten. Noch ein bisschen verwirrt auf '_.' Von dem, was ich verstehe, sagen wir ihm, dass er zum zweiten Punkt (dem Wert) des ersten (aktuellen) Paares gehen soll. – KChaloux

+2

@KChaloux In diesem Fall verweist '_' auf das erste Argument eines Funktionsliterals, das an die Methode' filter' übergeben wird. Es ist eine Abkürzung für 'x => x._2.isDefined' –

+0

Und das _2 stammt aus dem [Tuple] (http://www.scala-lang.org/api/current/index.html#scala.Tuple2). – fracz

41

Wenn Sie None Werte Ausfiltern sind, könnten Sie auch extrahieren Sie die Some Werte zugleich mit einem Map[String,Int] am Ende:

scala> map.collect { case (key, Some(value)) => (key, value) } 
res0: scala.collection.immutable.Map[String,Int] = Map(one -> 1, two -> 2) 
+0

Sehr cool, ich werde das überprüfen. – KChaloux

+1

Ich denke du kannst ohne die toMap wegkommen :-) –

6

auch map.filterKeys(map(_) != None)

oder

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

Dieser Ansatz stellt eine allgemeine Methode "filterValues" bereit, die in Maps nicht vorhanden ist.
Ich vermisse eine solche Methode, weil keine der Alternativen perfekt ist.

[Später aktualisiert] Dies ist eine bessere Version, die nicht auf jeden Eintrag nachschlägt und immer noch ziemlich klar liest.

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

Verwandte Themen