Tengo una clase pública definida en Kotlin: public class Edge(val v: Int, val u: Int, val weight: Double) que me ayuda a definir los bordes ponderados de un gráfico.
Ahora, en otra clase, necesito hacer una lista, que definí como var Sides = mutableListOf<Edge>() pero necesito ordenar la lista en orden ascendente que depende del tercer parámetro de Edge (que es el weight ). Así que si tengo la lista:
Lados = {Edge(4, 8, 4.1), Edge(20, 9, 7.5), Edge(5, 4, 0.0)}, se convierte en:
Lados = {Borde (5, 4, 0.0), Borde (4, 8, 4.1), Borde (20, 9, 7.5)}
¿Hay alguna función como .sort() que pueda usar para ordenar esta lista? ¿O tengo que hacer manualmente una función de un método de clasificación para esto?
Gracias por adelantado
Para una colección mutable como MutableList , puede usar la función sortBy para ordenar la lista original.
sides.sortBy { it.weight } Y, si tiene una colección inmutable como List , puede usar la función sortedBy que devuelve una nueva lista ordenada.
val sortedList = sides.sortedBy { it.weight } Además, tiene sortByDescending y sortedByDescending para clasificar en orden descendente.
Tienes dos enfoques básicos:
Edge un orden natural . Luego, todas las funciones de clasificación lo usarán de forma predeterminada, al igual que cualquier otra cosa que pueda usar un orden (como el orden de las claves en un SortedMap y el método binarySearch() ). Para ello, implemente la interfaz Comparable . Esto tiene un solo método, compareTo() , que podría ser tan simple como:
public class Edge(val v: Int, val u: Int, val weight: Double) : Comparable<Edge> { override fun compareTo(other: Edge) = weight.compareTo(other.weight) }Sin embargo, eso no da un orden consistente a las instancias que tienen el mismo peso, por lo que también puede usar las otras propiedades como desempates, por ejemplo:
override fun compareTo(other: Edge) = weight.compareTo(other.weight).takeIf{ it != 0 } ?: v.compareTo(other.v).takeIf{ it != 0 } ?: u.compareTo(other.u) (Hay algunas sutilezas en la implementación de eso, especialmente si no está anulando equals() para que se correspondan directamente. Vale la pena leer la documentación de Java ).
Tenga en cuenta que una data class implementa automáticamente Comparable , usando las propiedades en su constructor, en ese orden. Por lo tanto, generalmente no necesita preocuparse por ordenar eso.
Otras respuestas discuten esto. Quizás la forma más sencilla es:
sides.sortBy{ it.weight }Aunque hay muchas alternativas, como:
sides.sortWith{ a, b -> a.weight.compareTo(b.weight) } O podría crear una instancia de Comparator que podría reutilizarse según sea necesario:
val comparator = Comparator<Edge>{ o1, o2 -> o1.weight.compareTo(o2.weight) } sides.sortWith(comparator)Nuevamente, un comparador se puede usar con muchas funciones en la biblioteca estándar, por lo que puede evitar repetir el código de comparación de peso.
Qué enfoque elegir depende de sus necesidades.
Si tiene sentido intuitivo que sus bordes estén siempre ordenados por peso, entonces un orden natural sería una buena opción. Eso es conciso para el código: solo tiene que implementar Comparable en un lugar (o hacer que su clase sea una clase de data class con la propiedad de peso especificada primero), y luego obtendrá el beneficio completo de ordenar en todas partes. (Por supuesto, solo puede hacerlo si tiene control sobre el código fuente de Edge).
Por otro lado, si el orden basado en el peso es específico para un método en particular, si desea ordenar diferentes en otros lugares, entonces tendría más sentido especificar el orden cuando ordena.
Por supuesto, puede hacer ambas cosas, si es necesario: podría darle a su objeto un orden natural que se aplica a la mayoría de las cosas, pero luego especificar un orden diferente para operaciones particulares.