是否可能将以下代码表达为一次调用,跳过map和null的部分?
list.map(_.accept(this, arg).asInstanceOf[T]).filter(_ != null)
是否可能将以下代码表达为一次调用,跳过map和null的部分?
list.map(_.accept(this, arg).asInstanceOf[T]).filter(_ != null)
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
,但由于部分函数的isDefinedAt
测试,它可能会对大多数参数调用两次accept
:
list collect {
case i if i.accept(this, arg).asInstanceOf[T] != null => i.accept(this, arg).asInstanceOf[T]
}
为了避免这种情况,需要使用一些记忆化(或智能提取器)。
如果您关注性能,可以添加.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)
view
解释:https://dev59.com/lGw15IYBdhLWcg3wJ4YR#6799739
基本上,它使转换变得懒惰。 它甚至延迟了单个传递的执行,直到您调用toList
,此时它会进行单个传递,并在进行增量式地应用每个转换。 - Dan Burton
_.accept(this, arg)
可能会返回null
。在这种情况下,稍微更符合习惯的写法是(虽然仍需两个调用):list.map(i => Option(i.accept(this, arg).asInstanceOf[T])).flatten
。 - Tomasz Nurkiewiczcollect
不是map
和filter
的组合吗?还是反过来?或者我错了?;) - agilesteel