Reputation: 2551
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
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
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