Завжди просвітливо робити орієнтир на різні запропоновані відповіді. Ось що я дізнався:
#! / usr / bin / ruby
вимагають "орієнтиру"
арі = []
1000.times {
ary << {: bar => rand (1000)}
}
n = 500
Benchmark.bm (20) do | x |
x.report ("сортування") {n.times {ary.sort {| a, b | b [: bar] <=> a [: bar]}}}
x.report ("сортувати зворотний") {n.times {ary.sort {| a, b | a [: bar] <=> b [: bar]} .реверс}}
x.report ("sort_by -a [: bar]") {n.times {ary.sort_by {| a | -a [: бар]}}}
x.report ("sort_by a [: bar] * - 1") {n.times {ary.sort_by {| a | a [: бар] * - 1}}}
x.report ("sort_by.reverse!") {n.times {ary.sort_by {| a | a [: bar]} .реверс}}
кінець
система користувача загальна реальна
сортувати 3,960000 0,010000 3,970000 (3,990886)
сортувати реверс 4,040000 0,000000 4,040000 (4,038849)
sort_by -a [: бар] 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)
Я думаю, що цікаво, що @ Пабло sort_by{...}.reverse!
найшвидший. Перед тим, як запустити тест, я подумав, що це буде повільніше, ніж " -a[:bar]
", але, заперечуючи значення, знадобиться більше часу, ніж це для зворотного перетворення всього масиву за один прохід. Це не велика різниця, але кожен маленький прискорення допомагає.
Зауважте, що результати Ruby 1.9 відрізняються
Ось результати для Ruby 1.9.3p194 (2012-04-20 revision 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)
Вони є на старому MacBook Pro. Більш новіші або швидші машини матимуть менші значення, але відносні відмінності залишаться.
Ось трохи оновлена версія новітнього обладнання та версії Ruby 2.1.1:
#!/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)
Нові результати із застосуванням вищевказаного коду за допомогою Ruby 2.2.1 на останніх Macbook Pro. Знову ж таки, точні цифри не важливі, це їх відносини:
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)
Оновлено для Ruby 2.7.1 на MacBook Pro середини 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)
... зворотний метод насправді не повертає перевернутий масив - він повертає нумератор, який починається в кінці і працює назад.
Джерело для 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);
- це копіювання покажчиків на елементи у зворотному порядку, якщо я правильно запам’ятав свій C, тому масив перевернуто.