Je cherche à trier un tableau d'environ 200 à 300 objets, en triant sur une clé spécifique et un ordre donné (asc / desc). L'ordre des résultats doit être cohérent et stable.
Quel serait le meilleur algorithme à utiliser et pourriez-vous donner un exemple de son implémentation en javascript?
Merci!
javascript
algorithm
sorting
William Casarin
la source
la source
Réponses:
Il est possible d'obtenir un tri stable à partir d'une fonction de tri non stable.
Avant de trier, vous obtenez la position de tous les éléments. Dans votre condition de tri, si les deux éléments sont égaux, vous triez par position.
Tada! Vous avez une sorte stable.
J'ai écrit un article à ce sujet sur mon blog si vous voulez en savoir plus sur cette technique et comment la mettre en œuvre: http://blog.vjeux.com/2010/javascript/javascript-sorting-table.html
la source
Puisque vous recherchez quelque chose de stable, le tri par fusion devrait faire l'affaire.
http://www.stoimen.com/blog/2010/07/02/friday-algorithms-javascript-merge-sort/
Le code peut être trouvé sur le site Web ci-dessus:
ÉDITER:
Selon cet article , cela ressemble à Array.Sort dans certaines implémentations utilise un tri par fusion.
la source
Array#shift
peut fonctionner en temps O (n) et doncmerge
en O (n * n).Version un peu plus courte de la même chose utilisant des fonctionnalités ES2017 telles que les fonctions fléchées et la déstructuration:
Fonction
Il accepte le tableau d'entrée et la fonction de comparaison:
Il retourne également un nouveau tableau au lieu de faire un tri sur place comme le Array.sort () intégré fonction intégrée.
Tester
Si nous prenons le
input
tableau suivant , initialement trié parweight
:Puis triez-le en
height
utilisantstableSort
:Résulte en:
Cependant, trier le même
input
tableau en utilisant le intégréArray.sort()
(dans Chrome / NodeJS):Retour:
Ressources
Mettre à jour
la source
stableSort
fonction est une très bonne solution!Je sais que cette question a reçu une réponse depuis un certain temps, mais il se trouve que j'ai une bonne implémentation de tri de fusion stable pour Array et jQuery dans mon presse-papiers, je vais donc la partager dans l'espoir que certains futurs chercheurs pourraient la trouver utile.
Il vous permet de spécifier votre propre fonction de comparaison comme la normale
Array.sort
implémentation .la mise en oeuvre
Exemple d'utilisation
la source
array.sort
, voir test ici pour les chaînes et les entiers -> jsfiddle.net/QC64jmergeSort
et nonsort
, elle n'est donc pas destinée à remplacer. Parfois, vous avez juste besoin d'un tri de fusion stable, par exemple lors du tri des tables par colonne.Vous pouvez utiliser le polyfill suivant pour implémenter un tri stable quelle que soit l'implémentation native, en fonction de l'assertion faite dans cette réponse :
L'exécution des tests de performance implémentés ci-dessus
stableSort()
semble s'exécuter à environ 57% de la vitesse desort()
version 59-61 de Chrome.L'utilisation
.bind(compareFunction)
de la fonction anonyme enveloppée dans astableSort()
augmenté ces performances relatives d'environ 38% en évitant une référence de portée inutile àcompareFunction
chaque appel en l'attribuant au contexte à la place.Mettre à jour
Opérateur ternaire remplacé par un court-circuit logique, qui a tendance à mieux fonctionner en moyenne (semble faire une différence d'efficacité de 2 à 3%).
la source
Ce qui suit trie le tableau fourni, en appliquant la fonction de comparaison fournie, en retournant la comparaison d'index d'origine lorsque la fonction de comparaison renvoie 0:
L'exemple ci-dessous trie un tableau de noms par nom de famille, en conservant l'ordre des noms de famille égaux:
la source
jQuery.expando.split( "" ).sort( ( a, b ) => 0 ).join( "" ) === jQuery.expando
Voici une implémentation stable. Cela fonctionne en utilisant le tri natif, mais dans les cas où les éléments se comparent comme égaux, vous rompez les liens en utilisant la position d'index d'origine.
un test non approfondi
une autre réponse fait allusion à cela, mais n'a pas publié le codez.
mais, ce n'est pas rapide selon ma référence . J'ai modifié un outil de tri de fusion pour accepter une fonction de comparateur personnalisée, et c'était beaucoup plus rapide.
la source
Vous pouvez également utiliser Timsort. C'est un algorithme vraiment compliqué (plus de 400 lignes, donc pas de code source ici), alors voir la description de Wikipedia ou utilisez l'une des implémentations JavaScript existantes:
Implémentation GPL 3 . Présenté sous la forme Array.prototype.timsort. Semble être une réécriture exacte du code Java.
Implémentation du domaine public Conçu comme un tutoriel, l'exemple de code montre uniquement son utilisation avec des entiers.
Timsort est un hybride hautement optimisé de tri par fusion et de tri aléatoire et est l'algorithme de tri par défaut en Python et en Java (1.7+). C'est un algorithme compliqué, car il utilise des algorithmes différents pour de nombreux cas particuliers. Mais en conséquence, il est extrêmement rapide dans une grande variété de circonstances.
la source
Un simple mergeSort de http://www.stoimen.com/blog/2010/07/02/friday-algorithms-javascript-merge-sort/
la source
Je dois trier les tableaux multidimensionnels par une colonne arbitraire, puis par une autre. J'utilise cette fonction pour trier:
Notez que ary.sort ne renvoie jamais zéro, c'est là que certaines implémentations de la fonction "sort" prennent des décisions qui pourraient ne pas être correctes.
C'est sacrément rapide aussi.
la source
Voici comment vous pouvez étendre l'objet Array par défaut JS avec une méthode prototype utilisant MERGE SORT . Cette méthode permet de trier sur une clé spécifique (premier paramètre) et un ordre donné ('asc' / 'desc' comme deuxième paramètre)
Vous pouvez tester cela vous-même en déposant l'extrait ci-dessus dans la console de votre navigateur, puis en essayant:
Ou ordre basé sur un champ spécifique dans un tableau d'objets:
la source
J'avais donc besoin d'un tri stable pour mon application React + Redux, et la réponse de Vjeux m'a aidé. Cependant, ma solution (générique) semble différente des autres que je vois ici jusqu'à présent, donc je la partage au cas où quelqu'un d'autre aurait un cas d'utilisation correspondant:
sort()
API, où je peux passer une fonction de comparateur.Ma solution est de créer un tableau typé de
indices
, puis d'utiliser une fonction de comparaison pour trier ces indices en fonction du tableau à trier. Ensuite, nous pouvons utiliser le triéindices
pour trier le tableau d'origine ou créer une copie triée en un seul passage. Si cela est déroutant, pensez-y de cette façon: où vous passeriez normalement une fonction de comparaison comme:Vous utilisez maintenant à la place:
La vitesse est bonne; il s'agit essentiellement de l'algorithme de tri intégré, plus deux passes linéaires à la fin et une couche supplémentaire de surdébit d'indirection du pointeur.
Heureux de recevoir des commentaires sur cette approche. Voici ma mise en œuvre complète de celui-ci:
la source
Je sais que cela a reçu de nombreuses réponses. Je voulais juste publier une implémentation rapide de TS pour tous ceux qui ont atterri ici à la recherche de cela.
La méthode ne s'exécute plus sur place, comme le fait le tri natif. Je tiens également à souligner que ce n’est pas le plus efficace. Il ajoute deux boucles de l'ordre O (n). bien que le tri lui-même soit probablement O (n log (n)), il est donc inférieur à cela.
Certaines des solutions mentionnées sont plus performantes, pensant que cela pourrait être moins de code, utilisant également des
Array.prototype.sort
.(Pour une solution Javascript, supprimez simplement tous les types)
la source
Selon le blog de développement v8 , caniuse.com
Array.sort
est déjà stable, comme l'exige la spécification des navigateurs modernes, vous n'avez donc pas besoin de lancer votre propre solution. La seule exception que je peux voir est Edge, qui devrait bientôt passer au chrome et le supporter également.la source
la source
Le tri par comptage est plus rapide que le tri par fusion (il s'exécute en temps O (n)) et il est destiné à être utilisé sur des entiers.
Exemple:
la source
array [3, 1, 3]
hachages vers[undefined, 1, undefined, 3]
. Nous obtenons deux valeurs non indéfinies, alors que l'algorithme s'attend à ce qu'il y en ait trois.