Il est toujours instructif de faire un point de repère sur les différentes réponses suggérées. Voici ce que j'ai découvert:
#! / usr / bin / ruby
exiger une «référence»
ary = []
1000 fois {
ary << {: bar => rand (1000)}
}
n = 500
Benchmark.bm (20) do | x |
x.report ("sort") {n.times {ary.sort {| a, b | b [: bar] <=> a [: bar]}}}
x.report ("sort reverse") {n.times {ary.sort {| a, b | a [: bar] <=> b [: bar]} .reverse}}
x.report ("sort_by -a [: bar]") {n.times {ary.sort_by {| a | -un bar] } } }
x.report ("sort_by a [: bar] * - 1") {n.times {ary.sort_by {| a | un [: bar] * - 1}}}
x.report ("sort_by.reverse!") {n.times {ary.sort_by {| a | un [: bar]} .reverse}}
fin
système utilisateur total réel
trier 3,960000 0,010000 3,970000 (3,990886)
tri inversé 4.040000 0.000000 4.040000 (4.038849)
sort_by -a [: bar] 0,690000 0,000000 0,690000 (0,692080)
sort_by a [: bar] * - 1 0.700000 0.000000 0.700000 (0.699735)
sort_by.reverse! 0,650000 0,000000 0,650000 (0,654447)
Je pense que c'est intéressant que @ Pablo sort_by{...}.reverse!
soit le plus rapide. Avant d'exécuter le test, je pensais que ce serait plus lent que " -a[:bar]
" mais annuler la valeur s'avère plus long que pour inverser l'ensemble du tableau en une seule passe. Ce n'est pas vraiment une différence, mais chaque petite accélération aide.
Veuillez noter que ces résultats sont différents dans Ruby 1.9
Voici les résultats pour Ruby 1.9.3p194 (2012-04-20 révision 35410) [x86_64-darwin10.8.0]:
user system total real
sort 1.340000 0.010000 1.350000 ( 1.346331)
sort reverse 1.300000 0.000000 1.300000 ( 1.310446)
sort_by -a[:bar] 0.430000 0.000000 0.430000 ( 0.429606)
sort_by a[:bar]*-1 0.420000 0.000000 0.420000 ( 0.414383)
sort_by.reverse! 0.400000 0.000000 0.400000 ( 0.401275)
Ce sont sur un vieux MacBook Pro. Les machines plus récentes ou plus rapides auront des valeurs plus faibles, mais les différences relatives resteront.
Voici une version un peu mise à jour sur du matériel plus récent et la version 2.1.1 de Ruby:
#!/usr/bin/ruby
require 'benchmark'
puts "Running Ruby #{RUBY_VERSION}"
ary = []
1000.times {
ary << {:bar => rand(1000)}
}
n = 500
puts "n=#{n}"
Benchmark.bm(20) do |x|
x.report("sort") { n.times { ary.dup.sort{ |a,b| b[:bar] <=> a[:bar] } } }
x.report("sort reverse") { n.times { ary.dup.sort{ |a,b| a[:bar] <=> b[:bar] }.reverse } }
x.report("sort_by -a[:bar]") { n.times { ary.dup.sort_by{ |a| -a[:bar] } } }
x.report("sort_by a[:bar]*-1") { n.times { ary.dup.sort_by{ |a| a[:bar]*-1 } } }
x.report("sort_by.reverse") { n.times { ary.dup.sort_by{ |a| a[:bar] }.reverse } }
x.report("sort_by.reverse!") { n.times { ary.dup.sort_by{ |a| a[:bar] }.reverse! } }
end
# >> Running Ruby 2.1.1
# >> n=500
# >> user system total real
# >> sort 0.670000 0.000000 0.670000 ( 0.667754)
# >> sort reverse 0.650000 0.000000 0.650000 ( 0.655582)
# >> sort_by -a[:bar] 0.260000 0.010000 0.270000 ( 0.255919)
# >> sort_by a[:bar]*-1 0.250000 0.000000 0.250000 ( 0.258924)
# >> sort_by.reverse 0.250000 0.000000 0.250000 ( 0.245179)
# >> sort_by.reverse! 0.240000 0.000000 0.240000 ( 0.242340)
Nouveaux résultats exécutant le code ci-dessus en utilisant Ruby 2.2.1 sur un Macbook Pro plus récent. Encore une fois, les chiffres exacts ne sont pas importants, ce sont leurs relations:
Running Ruby 2.2.1
n=500
user system total real
sort 0.650000 0.000000 0.650000 ( 0.653191)
sort reverse 0.650000 0.000000 0.650000 ( 0.648761)
sort_by -a[:bar] 0.240000 0.010000 0.250000 ( 0.245193)
sort_by a[:bar]*-1 0.240000 0.000000 0.240000 ( 0.240541)
sort_by.reverse 0.230000 0.000000 0.230000 ( 0.228571)
sort_by.reverse! 0.230000 0.000000 0.230000 ( 0.230040)
Mis à jour pour Ruby 2.7.1 sur un MacBook Pro mi-2015:
Running Ruby 2.7.1
n=500
user system total real
sort 0.494707 0.003662 0.498369 ( 0.501064)
sort reverse 0.480181 0.005186 0.485367 ( 0.487972)
sort_by -a[:bar] 0.121521 0.003781 0.125302 ( 0.126557)
sort_by a[:bar]*-1 0.115097 0.003931 0.119028 ( 0.122991)
sort_by.reverse 0.110459 0.003414 0.113873 ( 0.114443)
sort_by.reverse! 0.108997 0.001631 0.110628 ( 0.111532)
... la méthode inverse ne retourne pas réellement un tableau inversé - elle retourne un énumérateur qui commence juste à la fin et fonctionne à l'envers.
La source de Array#reverse
est:
static VALUE
rb_ary_reverse_m(VALUE ary)
{
long len = RARRAY_LEN(ary);
VALUE dup = rb_ary_new2(len);
if (len > 0) {
const VALUE *p1 = RARRAY_CONST_PTR_TRANSIENT(ary);
VALUE *p2 = (VALUE *)RARRAY_CONST_PTR_TRANSIENT(dup) + len - 1;
do *p2-- = *p1++; while (--len > 0);
}
ARY_SET_LEN(dup, RARRAY_LEN(ary));
return dup;
}
do *p2-- = *p1++; while (--len > 0);
copie les pointeurs vers les éléments dans l'ordre inverse si je me souviens bien de mon C, donc le tableau est inversé.