是否可以通过一次调用表示map和null跳过来表达以下代码?
list.map(_.accept(this, arg).asInstanceOf[T]).filter(_ != null)
答案 0 :(得分:11)
list flatMap { i => Option(i.accept(this, arg).asInstanceOf[T]) }
或者,如果您愿意,(尽管这会或多或少地转换为原始表达式)
for {
item <- list
itemConverted = item.accept(this, arg).asInstanceOf[T]
itemNonNull = itemConverted if itemConverted != 0
} yield itemNonNull
使用collect
是可能的,但由于部分函数的accept
测试,它可能会在大多数参数上调用isDefinedAt
两次:
list collect {
case i if i.accept(this, arg).asInstanceOf[T] != null => i.accept(this, arg).asInstanceOf[T]
}
需要使用一些备忘录(或智能提取器)来避免这种情况。
答案 1 :(得分:7)
如果您担心效果,可以添加.view
list.view.map(_.accept(this, arg).asInstanceOf[T]).filter(_ != null)
view
会导致遍历变得懒惰,因此map
和filter
将在列表中的一次传递中执行,而不是两次单独传递。
如果您担心重复使用此模式,可以定义自己的辅助函数:
def mapNN[A,B](list: List[A])(f: A => B) = {
list.view.map(f(_)).filter(_ != null)
}
mapNN(list)(_.accept(this, arg).asInstanceOf[T])
...测试
> mapNN(List(1,2,3))(x => if (x%2==0) x else null).toList
res7: List[Any] = List(2)