Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala, make my loop more functional

I'm trying to reduce the extent to which I write Scala (2.8) like Java. Here's a simplification of a problem I came across. Can you suggest improvements on my solutions that are "more functional"?

Transform the map

val inputMap = mutable.LinkedHashMap(1->'a',2->'a',3->'b',4->'z',5->'c')

by discarding any entries with value 'z' and indexing the characters as they are encountered

First try

var outputMap = new mutable.HashMap[Char,Int]()
var counter = 0
for(kvp <- inputMap){
  val character = kvp._2
  if(character !='z' && !outputMap.contains(character)){
    outputMap += (character -> counter)
    counter += 1
  }
}

Second try (not much better, but uses an immutable map and a 'foreach')

var outputMap = new immutable.HashMap[Char,Int]()
var counter = 0
inputMap.foreach{
  case(number,character) => {
    if(character !='z' && !outputMap.contains(character)){
      outputMap2 += (character -> counter)
      counter += 1
    }
  }
}
like image 843
Pengin Avatar asked Dec 27 '10 18:12

Pengin


2 Answers

Nicer solution:

inputMap.toList.filter(_._2 != 'z').map(_._2).distinct.zipWithIndex.toMap
like image 190
Arjan Avatar answered Dec 05 '22 04:12

Arjan


I find this solution slightly simpler than arjan's:

inputMap.values.filter(_ != 'z').toSeq.distinct.zipWithIndex.toMap

The individual steps:

inputMap.values       // Iterable[Char]   = MapLike(a, a, b, z, c)
   .filter(_ != 'z')  // Iterable[Char]   = List(a, a, b, c)
   .toSeq.distinct    // Seq[Char]        = List(a, b, c)
   .zipWithIndex      // Seq[(Char, Int)] = List((a,0), (b,1), (c,2))
   .toMap             // Map[Char, Int]   = Map((a,0), (b,1), (c,2))

Note that your problem doesn't inherently involve a map as input, since you're just discarding the keys. If I were coding this, I'd probably write a function like

def buildIndex[T](s: Seq[T]): Map[T, Int] = s.distinct.zipWithIndex.toMap

and invoke it as

buildIndex(inputMap.values.filter(_ != 'z').toSeq)
like image 27
Aaron Novstrup Avatar answered Dec 05 '22 05:12

Aaron Novstrup