Tengo una lista de instancias simples de clases de casos de Scala y quiero imprimirlas en un orden lexicográfico predecible usando list.sorted
, pero recibo "Sin orden implícito definido para ...".
¿Existe un implícito que proporcione un orden lexicográfico para las clases de casos?
¿Existe una forma idiomática simple de mezclar el orden lexicográfico en la clase de caso?
scala> case class A(tag:String, load:Int)
scala> val l = List(A("words",50),A("article",2),A("lines",7))
scala> l.sorted.foreach(println)
<console>:11: error: No implicit Ordering defined for A.
l.sorted.foreach(println)
^
No estoy contento con un 'truco':
scala> l.map(_.toString).sorted.foreach(println)
A(article,2)
A(lines,7)
A(words,50)
scala
sorting
case-class
ya_pulser
fuente
fuente
Respuestas:
Mi método favorito personal es hacer uso del orden implícito proporcionado para Tuples, ya que es claro, conciso y correcto:
Esto funciona porque el compañero de
Ordered
define una conversión implícita deOrdering[T]
aOrdered[T]
que está dentro del alcance de la implementación de cualquier claseOrdered
. La existencia deOrdering
s implícitos paraTuple
s permite una conversión deTupleN[...]
aOrdered[TupleN[...]]
siempre queOrdering[TN]
exista un implícito para todos los elementosT1, ..., TN
de la tupla, lo que siempre debería ser el caso porque no tiene sentido ordenar un tipo de datos con noOrdering
.El orden implícito para Tuples es su opción para cualquier escenario de clasificación que involucre una clave de clasificación compuesta:
Como esta respuesta ha demostrado ser popular, me gustaría ampliarla, señalando que una solución similar a la siguiente podría, en algunas circunstancias, considerarse de nivel empresarial ™:
Dado
es: SeqLike[Employee]
,es.sorted()
ordenará por nombre yes.sorted(Employee.orderingById)
ordenará por id. Esto tiene algunos beneficios:Ordering
, por lo que proporcionar una ordenación directamente elimina una conversión implícita en la mayoría de los casos.fuente
value compare is not a member of (String, Int)
.Esto tiene la ventaja de que se actualiza automáticamente cada vez que A cambia. Sin embargo, los campos de A deben colocarse en el orden en que los utilizará el pedido.
fuente
<console>:12: error: not found: value unapply
Para resumir, hay tres formas de hacer esto:
Defina un pedido personalizado. El beneficio de esta solución es que puede reutilizar los pedidos y tener varias formas de ordenar instancias de la misma clase:
Respondiendo tu pregunta ¿Existe alguna función estándar incluida en Scala que pueda hacer magia como List ((2,1), (1,2)). Sorted
Hay un conjunto de ordenamientos predefinidos , por ejemplo, para String, tuplas hasta 9 arity y así sucesivamente.
No existe tal cosa para las clases de casos, ya que no es fácil de rodar, dado que los nombres de campo no se conocen a priori (al menos sin la magia de macros) y no puede acceder a los campos de clases de casos de otra manera que no sea por nombre / usando iterador de producto.
fuente
El
unapply
método del objeto complementario proporciona una conversión de su clase de caso a anOption[Tuple]
, dondeTuple
es la tupla correspondiente a la primera lista de argumentos de la clase de caso. En otras palabras:fuente
El método sortBy sería una forma típica de hacer esto, por ejemplo (ordenar por
tag
campo):fuente
l.sortBy( e => e._tag + " " + e._load + " " + ... )
?sortBy
, entonces sí, eso, o agregar / usar una función adecuada a / en la clase (por ejemplo_.toString
, o su propio método personalizado o función externa significativa lexográficamente).List((2,1),(1,2)).sorted
con los objetos de la clase case? No veo una gran diferencia entre las tuplas con nombre (clase de caso == tupla con nombre) y las tuplas simples.Option[TupleN]
, luego llamarget
a eso:,l.sortBy(A.unapply(_).get)foreach(println)
que usa el orden proporcionado en la tupla correspondiente, pero esto es simplemente un ejemplo explícito de la idea general que doy arriba .Como usó una clase de caso, puede extender con Ordered como tal:
fuente