2016-08-16 19 views
3

比方說,我有這種層次的爲我的數據:如何單獨的超類型的序列爲Seqs亞型

sealed trait Foolike 
case class Foo extends Foolike 
case class Bar extends Foolike 
case class Baz extends Foolike 

現在我想建立一個API,你可以把任何這些參數,像這樣的:

def apiMethod(modifiers: Foolike*) = { 


    val foos = modifiers 
    .filter(_.isInstanceOf[Foo]) 
    .map(_.asInstanceOf[Foo]) 

    val bars = modifiers 
    .filter(_.isInstanceOf[Bar]) 
    .map(_.asInstanceOf[Bar]) 

} 

是否有更好的方法來提取所有從modifiersFoo S和所有Bar S'

+0

我會建議使用case類模式匹配http://docs.scala-lang.org/tutorials/tour/case-classes.html – jerome

+2

'foos = modifiers.collect {case x:Foo => x}'and'bars = modifiers.collect {case x :Bar => x}'。類型也是你想要的! – Alec

回答

2
def apiMethod(modifiers: Foolike*) = { 

    @tailrec 
    def foosAndBarsAndBazs(mods: List[Foolike], foos: List[Foo], bars: List[Bar], bazs: List[Baz]): (List[Foo], List[Bar], List[Baz]) = mods match { 
     case Nil => (foos, bars, bazs) 
     case (foo: Foo) :: tail => foosAndBarsAndBazs(tail, foo :: foos, bars, bazs) 
     case (bar: Bar) :: tail => foosAndBarsAndBazs(tail, foos, bar :: bars, bazs) 
     case (baz: Baz) :: tail => foosAndBarsAndBazs(tail, foos, bars, baz :: bazs) 
    } 

    val (foos, bars, bazs) = foosAndBarsAndBazs(modifiers.toList, Nil, Nil, Nil)   
} 

這是一個尾遞歸解。當然,你可能只有map優先於修飾符和模式匹配才能得到一個Option s的元組,然後將它們弄平,但是隨後你會遍歷每個列表一次...

2

我不知道如果我理解你的目的,但你可以像這樣:

def apiMethod(modifiers: Foolike*) = new { 
    private val grouped = modifiers.groupBy(_.getClass) 
    .withDefaultValue(Nil) 

    def get[T <: Foolike](implicit m: Manifest[T]): Seq[T] = { 
    val clz = m.runtimeClass.asInstanceOf[Class[_ <: Foolike]] 
    grouped(clz).map(_.asInstanceOf[T]) 
    } 
} 

val result = apiMethod(Foo(), Bar(), Baz(), Bar()) 
result.get[Foo] // res0: Seq[Foo] = ArrayBuffer(Foo()) 
result.get[Bar] // res1: Seq[Bar] = ArrayBuffer(Bar(), Bar()) 
+0

我正在考慮類似的基於反射的解決方案。這很好,因爲它將支持所有'愚人'的子類型。 –

2

您可以使用摺疊此:

modifiers.foldRight((List[Foo](), List[Bar]())) { 
    case (x:Foo, (foos, bars)) => (x::foos, bars) 
    case (x:Bar, (foos, bars)) => (foos, x::bars) 
    case (_, acc) => acc 
} 
相關問題