Vraag Geef alleen op als patroon overeenkomt


Ik bouw een lijst met verschillende case class-objecten op basis van een loop en een patroonovereenkomst. Ik wil de items die de standaardcase raken, uitsluiten (overslaan) (in wezen de lijst filteren en in één stap toewijzen aan typen).

Ik ben waarschijnlijk te nieuw voor Scala om alle mogelijkheden te zien. Mijn poging:

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

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

    }

Ik zou de lijst achteraf kunnen filteren, maar ik vermoed dat er een of andere sjieke manier is om dit te doen :)

Laat het me weten als je enig idee hebt hoe dit het beste kan worden gedaan!


12
2018-02-27 21:00


oorsprong


antwoorden:


Het is niet dat het rendensyntaxis is, maar u kunt verzamelen gebruiken met patroonvergelijking:

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

In tegenstelling tot beter bekend .map en .foreach het zal niet falen in een "ander" geval en in plaats daarvan gewoon ongeëvenaarde items laten vallen.


28
2018-02-27 21:07



Het standaard filter in for-yield is verkregen met x <- y if f(x,..). Hier is een voorbeeld dat een gedeeltelijke functie gebruikt.

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)

Let op de gelijkenis met Traversable.collect1 vermeld in het andere antwoord, dat deze handtekening heeft def collect[B](pf: PartialFunction[A, B]): CC[B] en retourneert "een nieuwe verzameling die resulteert uit het toepassen van de gegeven gedeeltelijke functie pf op elk element waarop deze is gedefinieerd en het verzamelen van de resultaten".

Een alternatief zonder if is een variatie op het verwijderde antwoord van bwroga:

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

Dit filtert door vervolgens itereren door Geen (d.w.z. "0 items") of Some (d.w.z. "1 item") na de initiële kaart.


1 Als iemand me kan vertellen hoe ik naar individuele methoden in het "nieuwe" scaladoc moet linken, zou ik het zeer op prijs stellen.


9