Timo Westkämper
Timo Westkämper

Reputation: 22190

Combination of map and filter nulls out in Scala

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)

Upvotes: 8

Views: 19920

Answers (2)

Dan Burton
Dan Burton

Reputation: 53665

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)

Upvotes: 8

Debilski
Debilski

Reputation: 67838

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.

Upvotes: 11

Related Questions