Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: Best way to filter & map in one iteration

I'm new to Scala and trying to figure out the best way to filter & map a collection. Here's a toy example to explain my problem.

Approach 1: This is pretty bad since I'm iterating through the list twice and calculating the same value in each iteration.

val N = 5
val nums = 0 until 10
val sqNumsLargerThanN = nums filter { x: Int => (x * x) > N } map { x: Int => (x * x).toString }

Approach 2: This is slightly better but I still need to calculate (x * x) twice.

val N = 5
val nums = 0 until 10
val sqNumsLargerThanN = nums collect { case x: Int if (x * x) > N => (x * x).toString }

So, is it possible to calculate this without iterating through the collection twice and avoid repeating the same calculations?

like image 741
Can Bal Avatar asked Jun 15 '15 01:06

Can Bal


People also ask

How to filter Data in Scala?

Syntax. The following is the syntax of filter method. Here, p: (A) => Boolean is a predicate or condition to be applied on each element of the list. This method returns the all the elements of list which satisfiles the given condition.

How does filter work in Scala?

Scala filter is a method that is used to select the values in an elements or collection by filtering it with a certain condition. The Scala filter method takes up the condition as the parameter which is a Boolean value and returns the result after filtering over that condition.

Where vs filter in Spark?

The Spark where() function is defined to filter rows from the DataFrame or the Dataset based on the given one or multiple conditions or SQL expression. The where() operator can be used instead of the filter when the user has the SQL background. Both the where() and filter() functions operate precisely the same.


1 Answers

Could use a foldRight

nums.foldRight(List.empty[Int]) {
  case (i, is) =>
    val s = i * i
    if (s > N) s :: is else is
  }

A foldLeft would also achieve a similar goal, but the resulting list would be in reverse order (due to the associativity of foldLeft.

Alternatively if you'd like to play with Scalaz

import scalaz.std.list._
import scalaz.syntax.foldable._

nums.foldMap { i =>
  val s = i * i
  if (s > N) List(s) else List()
}
like image 167
adelbertc Avatar answered Nov 08 '22 11:11

adelbertc