2016-05-16 10 views
0

Ich habe eine PartialFunction[String,String] und eine Map[String,String]. Ich möchte die Teilfunktionen auf die Map-Werte anwenden und die Einträge sammeln, für die sie gültig waren. dh gegeben:Teilfunktion auf ein Tupelfeld anwenden, Aufrechterhaltung der Tupelstruktur

val m = Map("a"->"1", "b"->"2") 
val pf : PartialFunction[String,String] = { 
    case "1" => "11" 
} 

ich irgendwie möchte _._2 mit pf kombinieren und dies zu tun in der Lage:

val composedPf : PartialFunction[(String,String),(String,String)] = /*someMagicalOperator(_._2,pf)*/ 
val collected : Map[String,String] = m.collect(composedPf) 
// collected should be Map("a"->"11") 

bisher das beste, das ich erhielt, war dieses:

val composedPf = new PartialFunction[(String,String),(String,String)]{ 
     override def isDefinedAt(x: (String, String)): Boolean = pf.isDefinedAt(x._2) 
     override def apply(v1: (String, String)): (String,String) = v1._1 -> pf(v1._2) 
     } 

gibt es einen besseren Weg? Hier

Antwort

3

ist der magische Betreiber:

val composedPf: PartialFunction[(String, String), (String, String)] = 
    {case (k, v) if pf.isDefinedAt(v) => (k, pf(v))} 

Eine weitere Möglichkeit, ohne eine zusammengesetzte Funktion zu schaffen, ist dies:

m.filter(e => pf.isDefinedAt(e._2)).mapValues(pf) 
+0

Das sieht nach einer besseren Möglichkeit aus, was ich getan habe, ich suchte nach etwas allgemeinerem, vielleicht sogar nach Ootb in der Standardbibliothek. Wenn Sie darüber nachdenken, könnten Linsen die Lösung sein. –

+0

Ich verstehe, ich habe auch versucht, etwas ootb ohne Erfolg zu finden. Ich bezweifle, dass da etwas ist, weil man entweder Funktionen ganz anderer Art zusammenstellen müsste: '(String, String) => (String, String)' und 'String => String' oder eine Art" nest "einer Funktion in das andere, was mein Beispiel ist. So oder so, ich kann nicht einmal die Signatur einer solchen Kombinationsfunktion scheußlich sein. – Mifeet

+0

akzeptierte die Antwort. Ich werde hier updaten, wenn ich einen ordentlichen Weg finde, dies mit Objektiven zu erreichen. –

0

Es gibt eine Funktion in Scalaz, die genau das tut: second

scala> m collect pf.second 
res0: scala.collection.immutable.Map[String,String] = Map(a -> 11) 

Dies funktioniert, weil PartialFunction eine Instanz von ist Arrow (eine verallgemeinerte Funktion) typeclass und second ist eine der allgemeinen Operationen, die für Pfeile definiert sind.

+0

würde es immer noch funktionieren, wenn pf eine PartialFunction [String, Date] wäre? –

+0

@EyalFarago Sicher. "zweite" wandelt einen Pfeil "A => B" in einen Pfeil "(T, A) => (T, B)" um. Also würde "PartialFunction [String, Date]" in eine "PartialFunction [(T, String), (T, Date)]' 'konvertiert. Wenn Sie "pf.second" direkt in "collect" verwenden, kann Scala herausfinden, dass "T" "String" ist, aber in komplexeren Fällen müssen Sie explizit "T" angeben, z. 'pf.second [Zeichenfolge]'. – Kolmar

Verwandte Themen