2010-12-20 18 views
20

¿Hay algún motivo por el que no haya un pedido implícito de listas en Scala?¿Por qué las listas de Scala no tienen un pedido?

val lists = List(List(2, 3, 1), List(2, 1, 3)) 
lists.sorted 

error: could not find implicit value for parameter ord: Ordering[List[Int]] 

EDITAR

Sí, mi pregunta es por qué no hay una función de pedidos que ya está implícita en su alcance. Para mí, parece obvio que la segunda lista debe ser "menor que" la primera lista ya que los elementos en 0 son iguales y la segunda lista tiene el elemento inferior en 1. Me preguntaba si tal vez es que no hay una buena respuesta cuando el Las listas son de dos tamaños diferentes.

+2

orden lexicográfico (que describes) es definible para las listas de diferentes tamaños, aunque hay que tomar una decisión en cuanto a si las listas más cortas son mayores o menores que las listas más largas. Ambas formas se pueden usar para crear órdenes matemáticamente válidas, y mientras que la opción más larga tiene usos también. Esta podría ser la razón por la cual no hay un ordenamiento implícito provisto en las listas en la biblioteca estándar, pero todavía estoy seguro de que la falta de utilidad general es una razón más probable. –

Respuesta

42

Creo que es un descuido. El orden lexicográfico tiene sentido en Seqs. Deberíamos agregarlo a la biblioteca estándar.

+1

¡Gracias! Veo que trazaste un rastreador: http: // lampsvn.epfl.ch/trac/scala/ticket/4097 –

+0

¿Cuál es el valor predeterminado si el tipo de elemento no tiene una respuesta 'Ordering' no está' Ordered'? – Raphael

+0

¿Algún progreso con agregar a la biblioteca estándar? – user222202

4

Lo que tienes es una lista de listas, no una lista de enteros. Lo que se está perdiendo es un criterio para determinar si una lista es < = otra lista, o no.

Eso es lo que dice el mensaje de error: No puedo encontrar una manera de comparar una lista con otra, debe proporcionar una explícitamente.

Si su pregunta era "¿por qué no enumerar tiene un método de comparación incorporado contra otras listas?", Bueno, así es como es.

+0

Creo que su pregunta es por qué no hay criterios implícitos para determinar si una lista es <= otra lista. –

4

El único orden total realmente sensato sobre la clase de List [Int] sería lexicográfico (es decir, compara los primeros elementos de la lista, luego el segundo si son iguales, el tercero si los segundos son iguales, etc.) Esto no lo proporciona la biblioteca estándar, probablemente porque no hay muchos casos en los que realmente se necesite. Sería bastante fácil crear una conversión implícita de Lista [X] a Ordenar [Lista [X]] que implementaría eso, y luego simplemente podría importar esa conversión donde sea que la necesite.

1

Puede usar sortWith. Esto no tiene listas de diferentes tamaños en cuenta porque postal lanzará la diferencia, pero creo que hace algo como lo que está buscando:

lists.sortWith((a,b) => { 
    a.zip(b).filterNot(x => x._1 == x._2) match { 
    case Nil => true 
    case t => t._1 < t._2 
    } 
}) 
7

Por cierto, incluso antes me fijo que esto le podría hacer esto de otras maneras:

scala> List[Iterable[Int]](List(2, 3, 1), List(2, 1, 3)).sorted 
res0: List[Iterable[Int]] = List(List(2, 1, 3), List(2, 3, 1)) 

scala> List(List(2, 3, 1), List(2, 1, 3)).sorted(Ordering[Iterable[Int]]) 
res1: List[List[Int]] = List(List(2, 1, 3), List(2, 3, 1)) 

Pero ahora funciona como se esperaría.

Edición: debido a problemas de divergencia incompletos con el requisito implícito, lo saqué del alcance predeterminado. Tener una conversión implícita que actúa a través de un atado de esta manera:

implicit def SeqDerived[CC[X] <: collection.Seq[X], T](implicit ord: Ordering[T]): Ordering[CC[T]] 

... es una receta posibilidad de problemas. Estará disponible en 2.9, pero debes importarlo de la siguiente manera.

scala> val lists = List(List(2, 3, 1), List(2, 1, 3)) 
lists: List[List[Int]] = List(List(2, 3, 1), List(2, 1, 3)) 

scala> lists.sorted 
<console>:9: error: could not find implicit value for parameter ord: Ordering[List[Int]] 
     lists.sorted 
      ^

scala> import Ordering.Implicits._ 
import Ordering.Implicits._ 

scala> lists.sorted 
res1: List[List[Int]] = List(List(2, 1, 3), List(2, 3, 1)) 
Cuestiones relacionadas