Exia
Exia

Reputation: 2551

Sorting method in scala

I want to extend a sort method for scala Array which can return the original indecies.

The code I writed below:

object ArrayExtend {
implicit class ArrayExtension(val array: Array[Int]) {
    def argSort(): Array[Int] = {
                var tupleArray = for (i <- 0 until array.length) yield (i, array(i))     

                    tupleArray = tupleArray.sortWith((x,y)=> x._2 < y._2)

                    val result = for((index,_) <- tupleArray) yield index

                    return result.toArray

    }
}


def main(args:Array[String]){
val array = Array(5,4,3,2,0)
for(i <- array.argSort()) print(i)
}

}

This code works on Array[Int], how can I extend this method to all different types of Array? I didn't find any compare method in the AnyRef class.

Upvotes: 3

Views: 738

Answers (2)

Marek Adamek
Marek Adamek

Reputation: 520

It's enough if you require that type T can be implicitly converter into Ordered[T]. Normally it would be done by adding implicit converter to the class or method parameters with (implicit converter: T => Ordered[T]), however scala provides view bounds <% exactly for such cases. From the book: You can think of "T <% Ordered[T]" as saying. " I can use any T, as long as T can be treated as an Ordered[T]."

So the code would look like this:

implicit class ArrayExtension[T <% Ordered[T]](val array: Array[T]) {
  def argSort = array.zipWithIndex.sortBy(_._1).map(_._2).toArray
}

val array = Array(5,4,3,2,0)
val array2 = Array(5f,4f,3f,2f,0f)

array.argSort foreach print //43210
println
array2.argSort foreach print //43210

Upvotes: 8

Nader Ghanbari
Nader Ghanbari

Reputation: 4310

You can do this by using an implicit conversion to Ordered. You also need to parametrize your type. Change the code to the following:

implicit class ArrayExtension[T](val array: Array[T])(implicit view: (T) => Ordered[T]) {
  def argSort(): Array[Int] = {
    var tupleArray = for (i <- 0 until array.length) yield (i, array(i))
    tupleArray = tupleArray.sortWith((x, y) => x._2 < y._2)
    val result = for ((index, _) <- tupleArray) yield index
    result.toArray
 }

}

Ordered is

A trait for data that have a single, natural ordering.

and

Classes that implement this trait can be sorted with scala.util.Sorting and can be compared with standard comparison operators (e.g. > and <).

So any class that implements Ordered trait (directly or via an implicit conversion) can be used with sorting methods. You can implement this trait for your own data types in order to make them sortable.

Upvotes: 0

Related Questions