redes - ¿Cuál es la mejor manera de ordenar inversa en Scala?
informacion mediatica (9)
¿Cuál es la mejor manera de hacer una clasificación inversa en scala? Me imagino que lo siguiente es algo lento.
list.sortBy(_.size).reverse
¿Existe una forma conveniente de utilizar sortBy pero obteniendo un orden inverso? Preferiría no necesitar usar sortWith
.
Easy peasy (al menos en caso de size
):
scala> val list = List("abc","a","abcde")
list: List[java.lang.String] = List(abc, a, abcde)
scala> list.sortBy(-_.size)
res0: List[java.lang.String] = List(abcde, abc, a)
scala> list.sortBy(_.size)
res1: List[java.lang.String] = List(a, abc, abcde)
Otra posibilidad en caso de que pase una función que no podrá modificar directamente a un Arraybuffer mediante sortWith, por ejemplo:
val buf = collection.mutable.ArrayBuffer[Int]()
buf += 3
buf += 9
buf += 1
// the sort function (may be passed through from elsewhere)
def sortFn = (A:Int, B:Int) => { A < B }
// the two ways to sort below
buf.sortWith(sortFn) // 1, 3, 9
buf.sortWith((A,B) => { ! sortFn(A,B) }) // 9, 3, 1
Puede haber una forma obvia de cambiar el signo, si ordena por algún valor numérico
list.sortBy(- _.size)
De manera más general, la ordenación puede hacerse por método ordenado con un Pedido implícito, que puede explicitarse, y Ordenando tiene un reverso (no la lista al reverso más abajo) Puede hacer
list.sorted(theOrdering.reverse)
Si el orden que desea invertir es el orden implícito, puede obtenerlo implícitamente [Pedido [A]] (A del tipo que está ordenando) o mejor Orden [A]. Eso sería
list.sorted(Ordering[TheType].reverse)
sortBy es como usar Ordering.by, así que puedes hacer
list.sorted(Ordering.by(_.size).reverse)
Tal vez no sea el más corto para escribir (en comparación con menos) pero la intención es clara
Actualizar
La última línea no funciona. Para aceptar el _
en Ordering.by(_.size)
, el compilador necesita saber en qué tipo estamos ordenando, para que pueda escribir el _
. Puede parecer que sería el tipo del elemento de la lista, pero esto no es así, ya que la firma del ordenado se def sorted[B >: A](ordering: Ordering[B])
. El orden puede estar en A
, pero también en cualquier antecesor de A
(puede usar byHashCode : Ordering[Any] = Ordering.by(_.hashCode)
). Y, de hecho, el hecho de que la lista sea covariante obliga a esta firma. Uno puede hacer
list.sorted(Ordering.by((_: TheType).size).reverse)
pero esto es mucho menos agradable.
Tanto sortWith
como sortBy
tienen una sintaxis compacta:
case class Foo(time:Long, str:String)
val l = List(Foo(1, "hi"), Foo(2, "a"), Foo(3, "X"))
l.sortWith(_.time > _.time) // List(Foo(3,X), Foo(2,a), Foo(1,hi))
l.sortBy(- _.time) // List(Foo(3,X), Foo(2,a), Foo(1,hi))
l.sortBy(_.time) // List(Foo(1,hi), Foo(2,a), Foo(3,X))
Encuentro que el que tiene sortWith
más fácil de entender.
este es mi código;)
val wordCounts = logData.flatMap(line => line.split(" "))
.map(word => (word, 1))
.reduceByKey((a, b) => a + b)
wordCounts.sortBy(- _._2).collect()
tal vez para acortarlo un poco más:
def Desc[T : Ordering] = implicitly[Ordering[T]].reverse
List("1","22","4444","333").sortBy( _.size )(Desc)
sortBy
tiene un parámetro implicit que proporciona ordenamiento
def sortBy [B] (f: (A) ⇒ B)(implicit ord: Ordering[B]): List[A]
entonces, podemos definir el propio objeto Ordering
scala> implicit object Comp extends Ordering[Int] {
| override def compare (x: Int, y: Int): Int = y - x
| }
defined module Comp
List(3,2,5,1,6).sortBy(x => x)
res5: List[Int] = List(6, 5, 3, 2, 1)
list.sortBy(_.size)(Ordering[Int].reverse)
val list = List(2, 5, 3, 1)
list.sortWith(_>_) -> res14: List[Int] = List(5, 3, 2, 1)
list.sortWith(_<_) -> res14: List[Int] = List(1, 2, 3, 5)