Estoy buscando ordenar una matriz de aproximadamente 200-300 objetos, ordenando una clave específica y un orden dado (asc / desc). El orden de los resultados debe ser consistente y estable.
¿Cuál sería el mejor algoritmo para usar y podría proporcionar un ejemplo de su implementación en javascript?
¡Gracias!
javascript
algorithm
sorting
William Casarin
fuente
fuente
Respuestas:
Es posible obtener una clasificación estable a partir de una función de clasificación no estable.
Antes de ordenar obtienes la posición de todos los elementos. En su condición de ordenación, si ambos elementos son iguales, ordena por posición.
Tada! Tienes un tipo estable.
He escrito un artículo al respecto en mi blog si quieres saber más sobre esta técnica y cómo implementarla: http://blog.vjeux.com/2010/javascript/javascript-sorting-table.html
fuente
Dado que está buscando algo estable, la ordenación por combinación debería funcionar.
http://www.stoimen.com/blog/2010/07/02/friday-algorithms-javascript-merge-sort/
El código se puede encontrar en el sitio web anterior:
EDITAR:
Según esta publicación , parece que Array.Sort en algunas implementaciones usa una ordenación por combinación.
fuente
Array#shift
puede funcionar en O (n) tiempo y, por lo tanto, estámerge
en O (n * n).Versión algo más corta de lo mismo con funciones de ES2017 como funciones de flecha y desestructuración:
Función
Acepta matriz de entrada y función de comparación:
También devuelve una nueva matriz en lugar de realizar una ordenación en el lugar como el Array.sort () incorporado .
Prueba
Si tomamos la siguiente
input
matriz, inicialmente ordenada porweight
:Luego ordénelo
height
usandostableSort
:Resultados en:
Sin embargo, ordenando la misma
input
matriz usando el incorporadoArray.sort()
(en Chrome / NodeJS):Devoluciones:
Recursos
Actualizar
fuente
stableSort
función es una gran solución!Sé que esta pregunta ha sido respondida por algún tiempo, pero resulta que tengo una buena implementación estable de ordenación de fusión para Array y jQuery en mi portapapeles, así que la compartiré con la esperanza de que algunos futuros buscadores la encuentren útil.
Le permite especificar su propia función de comparación como la normal
Array.sort
implementación .Implementación
Ejemplo de uso
fuente
array.sort
, consulte la prueba aquí para cadenas y enteros -> jsfiddle.net/QC64jmergeSort
y nosort
, por lo que no pretende ser un reemplazo directo. A veces, solo necesita una clasificación de fusión estable, por ejemplo, al ordenar tablas por columna.Puede usar el siguiente polyfill para implementar una ordenación estable independientemente de la implementación nativa, según la afirmación realizada en esta respuesta :
Al ejecutar las pruebas de rendimiento implementadas anteriormente,
stableSort()
parece ejecutarse a aproximadamente el 57% de la velocidad desort()
versión 59-61 de Chrome.El uso
.bind(compareFunction)
de la función anónima envuelta dentrostableSort()
aumentó ese rendimiento relativo de aproximadamente un 38% al evitar una referencia de ámbito innecesaria acompareFunction
en cada llamada asignándola al contexto en su lugar.Actualizar
Se cambió el operador ternario a un cortocircuito lógico, que tiende a funcionar mejor en promedio (parece tener una diferencia del 2-3% en la eficiencia).
fuente
Lo siguiente ordena la matriz proporcionada, aplicando la función de comparación proporcionada, devolviendo la comparación de índice original cuando la función de comparación devuelve 0:
El siguiente ejemplo ordena una matriz de nombres por apellido, conservando el orden de apellidos iguales:
fuente
jQuery.expando.split( "" ).sort( ( a, b ) => 0 ).join( "" ) === jQuery.expando
Aquí hay una implementación estable. Funciona utilizando la ordenación nativa, pero en los casos en que los elementos se comparan como iguales, se rompen los vínculos utilizando la posición del índice original.
una prueba no exhaustiva
otra respuesta aludió a esto, pero no publicó el código.
pero no es rápido según mi punto de referencia . Modifiqué un impl de clasificación de combinación para aceptar una función de comparador personalizada, y fue mucho más rápido.
fuente
También puede utilizar Timsort. Este es un algoritmo realmente complicado (más de 400 líneas, por lo tanto, no hay código fuente aquí), así que consulte la descripción de Wikipedia o use una de las implementaciones de JavaScript existentes:
Implementación de GPL 3 . Empaquetado como Array.prototype.timsort. Parece ser una reescritura exacta del código Java.
Implementación de dominio público Concebido como un tutorial, el código de muestra solo muestra su uso con números enteros.
Timsort es un híbrido altamente optimizado de mergesort y shuffle sort y es el algoritmo de ordenación predeterminado en Python y en Java (1.7+). Es un algoritmo complicado, ya que utiliza diferentes algoritmos para muchos casos especiales. Pero, como resultado, es extremadamente rápido en una amplia variedad de circunstancias.
fuente
Un simple mergeSort de http://www.stoimen.com/blog/2010/07/02/friday-algorithms-javascript-merge-sort/
fuente
Tengo que ordenar matrices multidimensionales por una columna arbitraria y luego por otra. Utilizo esta función para ordenar:
Observe que ary.sort nunca devuelve cero, que es donde algunas implementaciones de la función "sort" toman decisiones que pueden no ser correctas.
Esto también es bastante rápido.
fuente
A continuación, le mostramos cómo puede extender el objeto Array predeterminado de JS con un método prototipo utilizando MERGE SORT . Este método permite ordenar por una clave específica (primer parámetro) y un orden dado ('asc' / 'desc' como segundo parámetro)
Puede probar esto usted mismo colocando el fragmento anterior en la consola de su navegador y luego intentando:
O haga un pedido basado en un campo específico en una matriz de objetos:
fuente
Así que necesitaba un tipo estable para mi aplicación React + Redux, y la respuesta de Vjeux aquí me ayudó. Sin embargo, mi solución (genérica) parece diferente a las otras que veo aquí hasta ahora, así que la comparto en caso de que alguien más tenga un caso de uso coincidente:
sort()
API, donde puedo pasar una función de comparación.Mi solución es crear una matriz con tipo de
indices
y luego usar una función de comparación para ordenar estos índices en función de la matriz que se va a ordenar. Luego, podemos usar sortedindices
para ordenar la matriz original o crear una copia ordenada en una sola pasada. Si eso es confuso, piénselo de esta manera: donde normalmente pasaría una función de comparación como:En su lugar, usa ahora:
La velocidad es buena; es básicamente el algoritmo de clasificación integrado, más dos pasadas lineales al final, y una capa adicional de sobrecarga de indirección del puntero.
Feliz de recibir comentarios sobre este enfoque. Aquí está mi implementación completa:
fuente
Sé que esto ha recibido muchas respuestas. Solo quería publicar una implementación rápida de TS para cualquiera que haya aterrizado aquí en busca de eso.
El método ya no se ejecuta en el lugar, como lo hace la ordenación nativa. También quiero señalar que no es el más eficiente. Agrega dos bucles del orden O (n). aunque la clasificación en sí misma es probablemente O (n log (n)), por lo que es menor que eso.
Algunas de las soluciones mencionadas son más eficaces, aunque podría ser menos código, también usando internos
Array.prototype.sort
.(Para una solución de Javascript, simplemente elimine todos los tipos)
fuente
De acuerdo con el blog de desarrollo v8 y caniuse.com
Array.sort
ya es estable como lo requieren las especificaciones en los navegadores modernos, por lo que no necesita desarrollar su propia solución. La única excepción que puedo ver es Edge, que pronto debería pasar al cromo y soportarlo también.fuente
fuente
La ordenación por conteo es más rápida que la ordenación por fusión (se realiza en tiempo O (n)) y está pensada para su uso en números enteros.
Ejemplo:
fuente
array [3, 1, 3]
hashes to[undefined, 1, undefined, 3]
. Obtenemos dos valores no indefinidos, mientras que el algoritmo espera que haya tres de ellos.