Combining map and filter values ​​in Scala

Is it possible to express the following code in such a way that mapping and passing zero is expressed in a single call?

list.map(_.accept(this, arg).asInstanceOf[T]).filter(_ != null) 
+6
source share
2 answers
 list flatMap { i => Option(i.accept(this, arg).asInstanceOf[T]) } 

or, alternatively, if you want (although this will be more or less converted 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 most likely it would call accept twice for most arguments because of the partial function's isDefinedAt tag:

 list collect { case i if i.accept(this, arg).asInstanceOf[T] != null => i.accept(this, arg).asInstanceOf[T] } 

To avoid this, you need to use some memoising (or smart extractors).

+11
source

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, so map and filter will be executed in one pass through the list, and not through two separate passes.

If you are concerned about reusing this template, 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) 
+6
source

Source: https://habr.com/ru/post/906462/


All Articles