如何将超类型的Sea分离成子类型的Seqs
How to seperate Seq of super type into Seqs of subtype
假设我的数据有这种层次结构:
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])
}
是否有更好的方法从 modifiers
中提取所有 Foo
和所有 Bar
?
我不确定我是否理解你的目的,但你可以这样做:
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())
您可以为此使用折叠:
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
}
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
的元组,然后将它们展平,但是您需要再遍历每个列表一次...
假设我的数据有这种层次结构:
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])
}
是否有更好的方法从 modifiers
中提取所有 Foo
和所有 Bar
?
我不确定我是否理解你的目的,但你可以这样做:
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())
您可以为此使用折叠:
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
}
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
的元组,然后将它们展平,但是您需要再遍历每个列表一次...