2013-02-27 12 views
12

Ich erstelle eine Liste von verschiedenen Fallklassenobjekten auf der Grundlage einer Schleife und einer Musterübereinstimmung. Ich möchte die Elemente ausschließen (überspringen), die den Standardfall (im Wesentlichen Filtern der Liste und Zuordnung zu Typen in einem Schritt) treffen.Ergebnis nur, wenn das Muster übereinstimmt

Ich bin wahrscheinlich zu neu zu Scala, um alle Möglichkeiten zu sehen. Mein Versuch:

val events = for (ev <- data) yield { 

     ev.sport match { 
      case "FOOTBALL" => new FootballEvent(ev) 
      case "SOCCER" => new SoccerEvent(ev) 
      case _ => None 
     } 

    } 

ich danach die Liste filtern konnte, aber ich vermute, es gibt einige Phantasie Scala Art und Weise, dies zu tun :)

Bitte lassen Sie mich wissen, wenn Sie eine Vorstellung davon haben, wie dies am besten getan werden sollte !

+0

Wenn es nur zwei Fälle gibt, statt drei oder mehr, kann dies in einer einzigen "for ... yield" erfolgen - hier ist ein Beispiel: 'for {Some (x) <- Some (None: Option [String])} yield "sollte nicht herkommen" ' –

Antwort

27

Es ist nicht, dass es Syntax ergeben, aber Sie können mit Mustervergleich verwenden sammeln:

val events = data.collect { ev => ev.sport match { 
    case "FOOTBALL" => new FootballEvent(ev) 
    case "SOCCER" => new SoccerEvent(ev) 
}} 

Im Gegensatz zu bekannteren .map und .foreach wird es nicht scheitern auf „anderem“ Fall und stattdessen nur fällt unerreichte Elemente.

+1

Ich überlasse es dir, da du zuerst geantwortet hast, aber keiner von uns hat es beim ersten Versuch richtig verstanden. Okay, sieht aus, als hättest du den Syntaxfehler behoben :) –

+0

habe nicht bemerkt, sammle b4. – javadba

9

Der Standardfilter in for-yield wird mit x <- y if f(x,..) erhalten. Hier ist ein Beispiel, das eine Teilfunktion verwendet.

val m: PartialFunction[Event, Event] = ev => ev.sport match { 
    case "FOOTBALL" => new FootballEvent(ev) 
    case "SOCCER" => new SoccerEvent(ev) 
}; 

for { ev <- data if m.isDefindAt(ev) 
     val x = m(ev) 
} yield x 

// or, without the temporary binding: 
for (ev <- data if m.isDefindAt(ev)) yield m(ev) 

Man beachte die Ähnlichkeit mit Traversable.collect in der anderen Antwort erwähnt, das diese Signatur hat def collect[B](pf: PartialFunction[A, B]): CC[B] und returns „eine neue Kollektion die sich aus der gegebenen Teilfunktion pf zu jedem Element der Anwendung auf dem es festgelegt wird, und Sammeln die Ergebnisse".

Eine Alternative ohne if ist eine Variation von bwroga ist gelöscht Antwort:

for { ev <- data; 
     x <- ev.sport match { 
     case "FOOTBALL" => Some(new FootballEvent(ev)) 
     case "SOCCER" => Some(new SoccerEvent(ev)) 
     case _ => None 
     } 
} yield x 

Diese Filter durch anschließend durch None (dh „0 Produkte“) oder einen Teil (zB „1 Punkt“) nach der ersten Karte Iterieren .


Wenn mir jemand, wie man einzelne Methoden in dem „neuen“ scaladoc verknüpfen kann sagen, ich sehr dankbar sein würde.

+1

Danke! Ich habe am Ende versucht, alle Ansätze – Joernsn

+0

Link zu den aktuellen Scaladocs für "scala.collection.Traversable" http://www.scala-lang.org/api/current/scala/collection/Traversable.html – Davos