2016-10-25 5 views
1

ich eine Eigenschaft haben, die wie folgt definiert ist:Scala Pattern Matching auf Allgemein Traits

sealed trait MyTrait[+A] { 
    def name: String 
    def id: Long 
    def someType: A 
} 

ich jetzt einige Fall Klassen, die diese Eigenschaft erstrecken, wie unten:

object MyTrait { 
    case class One[+A](name: String, id: Long, someField: String, someType: A) extends MyTrait[A] 

    case class Two[+A](name: String, id: Long, someField: String, someType: A) extends MyTrait[A] 

    case class Three[+A](name: String, id: Long, someType: A) extends MyTrait[A] 
} 

Nun, ich habe eine Liste, die eine dieser Fallklassen enthalten könnte und ich die Einzelfall-Klassen aus der gegebenen Liste zu sammeln, und ich verwende instanceOf prüft, wie unten:

val myBigList = List(One[SomeType], Two[SomeType], Three[SomeType], One[SomeType]) 

val allOnes = myBigList.collect { 
    case elem if elem.isInstanceOf[One[_]] => elem.asInstanceOf[One]] 
} 

val allTwos = myBigList.collect { 
    case elem if elem.isInstanceOf[Two[_]] => elem.asInstanceOf[Two]] 
} 

val allThrees = myBigList.collect { 
    case elem if elem.isInstanceOf[Three[_]] => elem.asInstanceOf[Three]] 
} 

Gibt es einen besseren Weg? Ich meine, gibt es eine Möglichkeit, die isInstanceOf und asInstanceOf zu vermeiden?

Antwort

3

Das ist gut, wenn Sie One[String] und One[Int] in einen Eimer bedeuten wollen, wenn Sie sich nicht um innere Typen kümmern.

Aber Sie können dies in einem einzigen Durchgang statt drei Durchgänge mit foldLeft tun.

def bucketize(list: List[MyTrait[_]]): (List[One[_]], List[Two[_]], List[Three[_]]) = { 
    list.foldLeft(((List.empty[One[_]], List.empty[Two[_]], List.empty[Three[_]]))){ (r, c) => 
    val ((one, two, three)) = r 
    c match { 
     case x: One[_] => ((one ++ List(x), two, three)) 
     case x: Two[_] => ((one, two ++ List(x), three)) 
     case x: Three[_] => ((one, two, three ++ List(x))) 
    } 
    } 
} 

Sie erhalten Triplett von Listen, erste Liste ist Liste [Ein], zweite Liste ist [Two] und so weiter ...

Nutzung:

val ((one, two, three)) = bucketize(list) 
+0

Wie in einem Arbeitsgang ? Ich brauche die individuellen Werte draußen! – sparkr

+0

@sparkr ... editiert die Antwort mit Beispiel. Bitte guck dir das an – pamu