Önerilen çeşitli cevaplar üzerinde bir kıyaslama yapmak her zaman aydınlatıcıdır. İşte buldum:
#! / Usr / bin / yakut
'kıyaslama' gerektir
ary = []
1000 x
ary << {: bar => rand (1000)}
}
n = 500
Benchmark.bm (20) yapmak | x |
x.report ("sıralama") {n.times {ary.sort {| a, b | b [: bar] <=> a [: bar]}}}
x.report ("ters sıralama") {n.times {ary.sort {| a, b | a [: bar] <=> b [: bar]} .reverse}}
x.report ("sort_by -a [: bar]") {n.times {ary.sort_by {| a | -bir bar] } } }
x.report ("sıralama_bir [: bar] * - 1") {n.times {ary.sort_by {| a | a [: bar] * - 1}}}
x.report ("sort_by.reverse!") {n.times {ary.sort_by {| a | a [: bar]} .reverse}}
son
kullanıcı sistemi toplam gerçek
sıralama 3.960000 0.010000 3.970000 (3.990886)
tersine sırala 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)
Sanırım @ Pablo'nun en sort_by{...}.reverse!
hızlı olması ilginç . Testi çalıştırmadan önce " -a[:bar]
" den daha yavaş olacağını düşündüm ama değeri reddetmek tüm diziyi bir geçişte tersine çevirmekten daha uzun sürüyor. Çok fazla bir fark yok, ama her hızlanma yardımcı oluyor.
Lütfen bu sonuçların Ruby 1.9'da farklı olduğunu unutmayın.
İşte Ruby 1.9.3p194 (2012-04-20 revizyon 35410) [x86_64-darwin10.8.0] sonuçları:
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)
Bunlar eski bir MacBook Pro'da. Daha yeni veya daha hızlı makineler daha düşük değerlere sahip olur, ancak göreli farklılıklar kalır.
İşte daha yeni bir donanımda biraz güncellenmiş sürüm ve Ruby'nin 2.1.1 sürümü:
#!/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)
Daha yeni bir Macbook Pro'da Ruby 2.2.1 kullanarak yukarıdaki kodu çalıştıran yeni sonuçlar. Yine, tam sayılar önemli değil, ilişkileri.
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)
2015 Ortası MacBook Pro'da Ruby 2.7.1 için güncellendi:
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)
... tersine yöntem tersine çevrilmiş bir diziyi döndürmez - en sonunda başlayan ve geriye doğru çalışan bir numaralandırıcı döndürür.
Kaynağı Array#reverse
:
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);
benim C doğru hatırlıyorsanız, işaretçiler öğelere ters sırayla kopyalanıyor, böylece dizi ters.