Scala, make my cycle more functional

I am trying to reduce the extent to which I write Scala (2.8) as Java. Here's a simplification of the problem I encountered. Can you suggest improvements to my solutions that are “more functional”?

Map conversion

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

discarding any entries with a value of 'z' and indexing characters when they occur

Try first

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
  }
}

The second attempt (not much better, but uses an immutable map and "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
    }
  }
}
+5
source share
6 answers

Nicer Solution:

inputMap.toList.filter(_._2 != 'z').map(_._2).distinct.zipWithIndex.toMap
+11
source

I find this solution a little easier than arjan's :

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

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))

: , . , , , ​​,

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

buildIndex(inputMap.values.filter(_ != 'z').toSeq)
+9

-, , .

, -, filter:

inputMap.filter(_._2 != 'z')

, , , ( ) zipWithIndex, , :

inputMap.filter(_._2 != 'z').values.toSet.zipWithIndex.toMap

*, , -, , , , .

Edit: ; . . (*) , LinkedHashMap. , , Arjan.

+5

"", , , , . List.map , , .

inputMap
.toList // List((5,c), (1,a), (2,a), (3,b), (4,z))
.sorted // List((1,a), (2,a), (3,b), (4,z), (5,c))
.filterNot((x) => {x._2 == 'z'}) // List((1,a), (2,a), (3,b), (5,c))
.map(_._2) // List(a, a, b, c)
.zipWithIndex // List((a,0), (a,1), (b,2), (c,3))
.map((x)=>{(x._2+1 -> x._1)}) // List((1,a), (2,a), (3,b), (4,c))
.toMap // Map((1,a), (2,a), (3,b), (4,c))

.

+3

: OP - , . :

val values = inputMap.values.filterNot(_ == 'z').toSet.zipWithIndex.toMap

2: , toSeq.distinct , .

val values = inputMap.values.filterNot(_ == 'z').toSeq.distinct.zipWithIndex.toMap
+2

, . , , .

, , . , , , , append O (1). , .. , . , - /.

However, I still think there should be better support for filtering, collating and collapsing / minimizing maps. Since we start with a map, we know the maximum size of a map, and it should be easy to create.

If you want to access functional programming, I would recommend starting with cards from the beginning. Stick to the fact that functional languages ​​have been designed to manipulate lists.

-2
source

All Articles