Scala:基于类型过滤 [英] Scala: Filtering based on type
问题描述
我正在学习Scala,因为它适合我的需要,但我发现很难结构代码优雅。我在一个列表
x
并且想要创建两个列表
s:一个包含 SomeClass
的所有元素,一个包含所有不是 SomeClass
。
I'm learning Scala as it fits my needs well but I am finding it hard to structure code elegantly. I'm in a situation where I have a List
x
and want to create two List
s: one containing all the elements of SomeClass
and one containing all the elements that aren't of SomeClass
.
val a = x collect {case y:SomeClass => y}
val b = x filterNot {_.isInstanceOf[SomeClass]}
我的代码看起来像。然而,它不是很有效,因为它重复 x
两次,代码看起来有点怪。是否有更好的(更优雅的)处理方式?
Right now my code looks like that. However, it's not very efficient as it iterates x
twice and the code somehow seems a bit hackish. Is there a better (more elegant) way of doing things?
可以假设 SomeClass
没有子类。
推荐答案
已编辑
使用简单分区
是可能的,它丢失了 collect
在问题中保留的类型信息。
While using plain partition
is possible, it loses the type information retained by collect
in the question.
可以定义分区
方法的变体,该方法接受一个函数,使用返回两种类型之一的值,
One could define a variant of the partition
method that accepts a function returning a value of one of two types using Either
:
import collection.mutable.ListBuffer
def partition[X,A,B](xs: List[X])(f: X=>Either[A,B]): (List[A],List[B]) = {
val as = new ListBuffer[A]
val bs = new ListBuffer[B]
for (x <- xs) {
f(x) match {
case Left(a) => as += a
case Right(b) => bs += b
}
}
(as.toList, bs.toList)
}
然后保留类型:
scala> partition(List(1,"two", 3)) {
case i: Int => Left(i)
case x => Right(x)
}
res5: (List[Int], List[Any]) = (List(1, 3),List(two))
当然,使用构建器和所有改进的集合东西可以改进解决方案:)。
Of course the solution could be improved using builders and all the improved collection stuff :) .
为了完整性,我的旧答案使用简单的分区
:
For completeness my old answer using plain partition
:
val (a,b) = x partition { _.isInstanceOf[SomeClass] }
例如:
scala> val x = List(1,2, "three")
x: List[Any] = List(1, 2, three)
scala> val (a,b) = x partition { _.isInstanceOf[Int] }
a: List[Any] = List(1, 2)
b: List[Any] = List(three)
这篇关于Scala:基于类型过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!