Is it possible to express the following code in such a way that the map and null skipping is expressed in one call?
list.map(_.accept(this, arg).asInstanceOf[T]).filter(_ != null)
list flatMap { i => Option(i.accept(this, arg).asInstanceOf[T]) }
or alternatively, if you like, (though this will be converted more or less to your original expression)
for {
item <- list
itemConverted = item.accept(this, arg).asInstanceOf[T]
itemNonNull = itemConverted if itemConverted != 0
} yield itemNonNull
Using collect
would be possible but it would likely call accept
twice on most arguments because of the isDefinedAt
test of the partial function:
list collect {
case i if i.accept(this, arg).asInstanceOf[T] != null => i.accept(this, arg).asInstanceOf[T]
}
One would need to use some memoising (or smart extractors) to avoid this.
If you are concerned about performance, you can add .view
list.view.map(_.accept(this, arg).asInstanceOf[T]).filter(_ != null)
view
causes the traversal to become lazy, thus the map
and filter
will be performed in one pass over the list rather than two separate passes.
If you are concerned about reusing this pattern, you can define your own helper function:
def mapNN[A,B](list: List[A])(f: A => B) = {
list.view.map(f(_)).filter(_ != null)
}
mapNN(list)(_.accept(this, arg).asInstanceOf[T])
Testing...
> mapNN(List(1,2,3))(x => if (x%2==0) x else null).toList
res7: List[Any] = List(2)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With