Jon Deaton
Jon Deaton

Reputation: 4379

Scala count number of times function returns each value, functionally

I want to count up the number of times that a function f returns each value in it's range (0 to f_max, inclusive) when applied to a given list l, and return the result as an array, in Scala.

Currently, I accomplish as follows:

 def count (l: List): Array[Int] = {
    val arr = new Array[Int](f_max + 1)
    l.foreach {
      el => arr(f(el)) += 1
    }
    return arr
  }

So arr(n) is the number of times that f returns n when applied to each element of l. This works however, it is imperative style, and I am wondering if there is a clean way to do this purely functionally.

Thank you

Upvotes: 0

Views: 229

Answers (2)

rad i
rad i

Reputation: 294

how about a more general approach:

def count[InType, ResultType](l: Seq[InType], f: InType => ResultType): Map[ResultType, Int] = {
  l.view                              // create a view so we don't create new collections after each step
    .map(f)                           // apply your function to every item in the original sequence
    .groupBy(x => x)                  // group the returned values
    .map(x => x._1 -> x._2.size)      // count returned values
}

val f = (i:Int) => i
count(Seq(1,2,3,4,5,6,6,6,4,2), f)

Upvotes: 1

Levi Ramsey
Levi Ramsey

Reputation: 20561

l.foldLeft(Vector.fill(f_max + 1)(0)) { (acc, el) =>
  val result = f(el)
  acc.updated(result, acc(result) + 1)
}

Alternatively, a good balance of performance and external purity would be:

def count(l: List[???]): Vector[Int] = {
  val arr = l.foldLeft(Array.fill(f_max + 1)(0)) { (acc, el) =>
    val result = f(el)
    acc(result) += 1
  }
  arr.toVector
}

Upvotes: 0

Related Questions