2017-12-06 2 views
0

Ich habe ein Map[String, Int]scala: Dynamisch mit Prädikaten Filterung

val labelMap: mutable.HashMap[String, Int] = sparse0.sparseOperationCountRowsByTarget() 

ich die Karte in einer Anweisung filtern möchten. Der Filter kann sowohl filtern, indem String oder Int

In gröbsten Form es wie folgt aussieht:

val labelMapFiltered = labelMap.filter(label => label._1.startsWith("REL") || label._2 < 400) 

Jetzt habe ich bereits allgemeine Nützlichkeit Prädikate für Streich- und Int-Funktionen. Zeichenfolgenprädikate sind:

object StringPredicates 
{ 
    def stringEquals(required:String)(input:String) = input == required 
    def stringStartsWith(required:String)(input:String) = input.startsWith(required) 
    def stringContains(required:String)(input:String) = input.contains(required) 



    def and(predicates:Seq[String => Boolean])(input:String) = predicates.forall(predicate => predicate(input)) 
    def or(predicates:Seq[String => Boolean])(input:String) = predicates.exists(predicate => predicate(input)) 
} 

Int Prädikate sind das gleiche Muster wie oben.

Dies ermöglicht die folgenden Filter:

val sw1=stringContains("#") 
val sw2=stringStartsWith("REL") 
val sw3=intGT(400) 



     val labelMapFiltered = labelMap.filter(label =>sw1(label._1) || sw2(label._1) || sw3(label._2)) 

ich die Prädikate in die Funktion übergeben werden sollen (als Seq, nehme ich an) und dann filtern. So wie Ich suche etwas:

val labelMapFiltered = labelMap.filter(myFunction(myPredSeq)) 

Kann ich das die Prädikate mit habe ich schon? Das Schreiben von Prädikaten für Tuple2[String,Int], die mit der spezifischen Map in dieser Funktion übereinstimmen, erscheint zu spezifisch. Ich müsste dann Prädikate für jede Art von Map schreiben, die ich filtern möchte.

Antwort

3

Sie

val sw1: (String, Int) => Boolean = stringContains("#").compose(kv: (String, Int) => kv._1) 

Oder sogar das gleiche tun, aber Mapping ove: Ihre Prädikate in die Annahme des entsprechenden Typs mit der compose Methode, zB transformieren r Ihre Prädikate:

val predsOfTuples1 = predsOfStrings.map(_.compose(kv: (String, Int) => kv._1))) 
val predsOfTuples2 = predsOfInts.map(_.compose(kv: (String, Int) => kv._2)) 
val preds = predsOfTuples1 ++ predsOfTuples2 

Das letzte, was Sie tun müssen, würde sich, Ihre and und or Methoden generisch, so dass Sie sie auf Prädikate von Tupeln verwenden können:

def and[A](predicates:Seq[A => Boolean])(input:A) = predicates.forall(predicate => predicate(input)) 
def or[A](predicates:Seq[A => Boolean])(input:A) = predicates.exists(predicate => predicate(input)) 
+0

Die Scala Designer haben an alles gedacht :) – Jake

0

Lassen Sie uns die Eingabe vereinfachen und eine einfache Liste von Int s betrachten:

List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 

Sie können in einem Stream alle Prädikate stellen (so dass sie faul ausgewertet und Sie müssen alle nicht beurteilen von ihnen):

val predicates = Stream((n: Int) => n == 0, (n: Int) => n % 2 == 1, (n: Int) => n >= 8) 

Die Regeln sind, dass die Zahlen gehalten werden, wenn sie 0, ungerade oder größer oder gleich 8

Jetzt sind wir wenn mindestens ein Prädikat in unserer Sammlung filtern fragen, indem Sie ist die true zurückgibt:

list.filter(n => predicates.exists(p => p(n))) 

Die Ausgabe ist eine Liste von Zahlen, dass die Achtung mindestens eine der Regeln:

List(0, 1, 3, 5, 7, 8, 9) 
+0

Das ist sehr hilfreich, aber ich bin nicht sicher, wie das funktionieren würde, wenn ich sowohl nach String als auch nach Int (sowohl nach Schlüssel als auch nach Wert) filtern würde. – Jake