What is the best way, if at all, to implement a sorting function with internal state?

Viewed 47

What is the best way to implement a sorting function that has an internal state received else where?

Something like:

  type Sorter[Item] = (Item, Item) => Boolean

  type StringSorter = Sorter[String]

  def customSorter : StringSorter = (i1,i2) =>
   {
    val i1Cnt = itemCountMap.get(i1)
    val i2Cnt = itemCountMap.get(i2)
    if (i1Cnt==None || i2Cnt==None ) {
       i1<i2
    } else {
      i1Cnt.get<i2Cnt.get
    }
  }

And here is an example:

val l1 = List("a","b","c")
val itemCountMap = Map("a"->2,"b"->3,"c"1)

l1.sortWith(customSorter)
//The returned list will be ["c","a","b"]

I am pretty new to Scala, and in general, lambda functions are not suppose to have states (right?).

Why you ask? 'cause I am using a generic type lists in spark which later, deep in the code of the executors, I want to analyze based on a specific order, and this order may depend on some static list, and I also want to control this order function.

1 Answers

First, this i1Cnt==null will never be true because get on Map never returns null, it returns an Option WHICH IS NOT A NULL, it is very different.

Second, there is no problem with state in a lambda, there is a problem with mutable shared state (and not only in a lambda, but everywhere).

Third, your function would be better if it receives the Map to use instead of relying on a global variable.

Fourth, here is the fixed code.

type Sorter[Item] = (Item, Item) => Boolean

def customSorter(map: Map[String, Int]): Sorter[String] = { (s1, s2) =>
  (map.get(s1), map.get(s2)) match {
    case (Some(i1), Some(i2)) => i1 < i2
    case _                    => s1 < s2
  }
}

You can see it running here)

Related