Tri d'un tableau de chaînes de caractères en Ruby
J'ai appris tableau deux méthodes de tri en Ruby:
array = ["one", "two", "three"]
array.sort.reverse!
ou:
array = ["one", "two", "three"]
array.sort { |x,y| y<=>x }
Et je ne suis pas en mesure de différencier entre les deux. Quelle méthode est la meilleure et comment exactement sont-ils différents dans l'exécution?
- Ces poils d'une question. C'est la même méthode
#sort
, et pour la mise en œuvre deatils, n'hésitez pas à consulter code source C, ruby-doc.org/core-2.0/Array.html#method-i-sort. - Aparté: Si vous avez besoin d'un discbased en Ruby qui prend en charge la plupart des Énumérable les méthodes et les trie et stocke les données uniques, vous voudrez peut-être regarder à SortedSet.
Vous devez vous connecter pour publier un commentaire.
Les deux lignes d'en faire de même (créer un nouveau tableau, qui est l'inverse triés). L'argument principal est sur la lisibilité et la performance.
array.sort.reverse!
est plus lisible quearray.sort{|x,y| y<=>x}
- je pense que nous pouvons convenir ici.Pour la performance de la partie, j'ai créé un rapide test de script, ce qui donne la suite sur mon système (
ruby 1.9.3p392 [x86_64-linux]
):Temps d'exécution sont assez constante pour plusieurs exécutions de l'indice de référence de script.
array.sort.reverse
(avec ou sans!
) est beaucoup plus rapide quearray.sort{|x,y| y<=>x}
. Donc, je recommande.Voici le script de Référence:
master = (1..1000000).map(&:to_s).shuffle
et puis définisseza = master.clone
avant chaque rapport de référence, de sorte qu'ils sont tous de tri exactement la même chose. J'ai aussi augmenté la taille de 1_000_000, et ajout d'une référence poura.sort!.reverse!
. Sur mon système (ruby 2.0.0p195 [x86_64-darwin12.3.0]
) à l'aide sur placea.sort!.reverse!
est sorti vainqueur.reverse!
dans cette réponse, c'est gaspiller de l'UC. C'est en essayant de modifier un tableau temporaire créé lors desort
a remis son tableau, ce qui n'aide pas.reverse
est plus rapide que l'utilisationsort_by
ousort
avec inversée ou annulés les résultats dans le bloc, ce qui nous a surpris.sort!.reverse!
est plus rapide car sa mutation le tableau d'origine.array.sort.reverse!
est légèrement plus rapide pour1.9.3
.Il n'y a vraiment pas de différence ici. Les deux méthodes renvoient un nouveau tableau.
Pour les besoins de cet exemple, le plus simple est mieux. Je recommande
array.sort.reverse
car il est beaucoup plus lisible que l'alternative. En passant blocs de méthodes commesort
doit être enregistrée pour des tableaux plus complexes structures de données et les classes définies par l'utilisateur.Edit: Tout
destructive
méthodes (tout se terminant par un !) sont bon pour la performance des jeux, il a été souligné qu'ils ne sont pas nécessaire pour retourner une mise à jour de tableau, ou quoi que ce soit d'ailleurs. Il est important de garder cela à l'esprit, cararray.sort.reverse!
pourrait très probablement de retournil
. Si vous souhaitez utiliser une méthode destructive sur un nouvellement généré tableau, vous devez préfère les appeler.reverse!
sur une ligne distincte au lieu d'avoir un one-liner.Exemple:
devrait être préféré à
reverse!
doit retourner une mise à jour du tableau. Il a seulement mettre à jour l'objet appelé. Le premier est une tâche de la non-destructive version.Inverse! est plus Rapide
Il n'y a souvent pas de substitut pour l'analyse comparative. Alors qu'il fait probablement pas de différence en plus courte, les scripts, le #inverse! la méthode est beaucoup plus rapide que le tri à l'aide de la "vaisseau spatial" de l'opérateur. Par exemple, sur l'IRM Ruby 2.0, et compte tenu de la référence ci-après code:
le système vous signale que #inverse! est presque deux fois plus rapide que d'utiliser le combiné opérateur de comparaison.
Mon conseil: utiliser celle qui est la plus sémantiquement pertinente dans un contexte donné, sauf si vous êtes en cours d'exécution dans une boucle serrée.
Comparaison avec d'aussi simple que votre exemple, il n'y a pas beaucoup de différence, mais comme la formule pour la comparaison devient compliqué, il est préférable d'éviter d'utiliser
<=>
avec un bloc parce que le bloc que vous transmettez seront évalués pour chaque élément du tableau, provoquant la redondance. Considérez ceci:Dans ce cas,
some_expensive_method
sera évaluée pour chaque paire possible de l'élément dearray
.Dans votre cas particulier, l'utilisation d'un bloc avec
<=>
peut être évité avecreverse
.Ce qui est appelé Schwartzian transformer.
sort_by
? Parce que c'est ce que l'OP est en train de faire.En jouant avec tessi repères sur ma machine, j'ai obtenu quelques résultats intéressants. Je suis en cours d'exécution
ruby 2.0.0p195 [x86_64-darwin12.3.0]
, c'est à dire, la dernière version de Ruby 2 sur un OS X système. J'ai utilisé bmbm plutôt quebm
de l'indice de Référence du module. Mes horaires sont:Tout d'abord, notez que dans la Répétition de la phase de
sort!
à l'aide d'un bloc de comparaison est le gagnant clair. Matz doit avoir réglé le diable hors de lui en Ruby 2!L'autre chose que je trouve extrêmement bizarre était de savoir comment beaucoup d'amélioration
array.sort.reverse!
etarray.sort!.reverse!
exposées dans la production de passe. Il était tellement extrême, il m'a fait me demander si j'avais quelque vissé vers le haut et transmis ces données sont triées, j'ai donc ajouté explicite vérifie triés ou d'inversion de données triées avant d'effectuer chaque test.Ma variante de tessi du script suit: