Сортировка массива в порядке убывания в Ruby

У меня есть массив хешей как следующее

[
  { :foo => 'foo', :bar => 2 },
  { :foo => 'foo', :bar => 3 },
  { :foo => 'foo', :bar => 5 },
]

Я пытаюсь отсортировать выше массива в порядке убывания согласно значению :bar в каждом хеше.

Я использую sort_by как следующее к виду выше массива.

a.sort_by { |h| h[:bar] }

Однако выше видов массив в порядке возрастания. Как я делаю это видом в порядке убывания?

Одно решение состояло в том, чтобы сделать следующее:

a.sort_by { |h| -h[:bar] }

Но тот знак минус не кажется соответствующим. Какие-либо представления?

266
задан Waseem 14 April 2010 в 14:32
поделиться

4 ответа

Всегда полезно проверять различные предлагаемые ответы. Вот что я узнал:

#!/usr/bin/ruby

require 'benchmark'

ary = []
1000.times { 
  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| -a[:bar] } } }
  x.report("sort_by a[: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 } }
end

                          user     system      total        real
sort                  3.960000   0.010000   3.970000 (  3.990886)
sort reverse          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)

Думаю, интересно, что @Pablo sort_by {...}. Перевернул! самый быстрый. Перед запуском теста я думал, что он будет медленнее, чем " -a [: bar] ", но отрицание значения, как выяснилось, занимает больше времени, чем обращение всего массива за один проход. Это не большая разница, но каждое небольшое ускорение помогает.


Обратите внимание, что эти результаты отличаются в Ruby 1.9

Вот результаты для Ruby 1.9.3p194 (2012-04-20, редакция 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)
538
ответ дан 23 November 2019 в 02:24
поделиться

Простая вещь, обозначающая намерение нисходящего порядка.

descending = -1
a.sort_by { |h| h[:bar] * descending }

(А пока придумаю способ получше);)


a.sort_by { |h| h[:bar] }.reverse!
86
ответ дан 23 November 2019 в 02:24
поделиться

А как насчет:

 a.sort {|x,y| y[:bar]<=>x[:bar]}

Работает !!

irb
>> a = [
?>   { :foo => 'foo', :bar => 2 },
?>   { :foo => 'foo', :bar => 3 },
?>   { :foo => 'foo', :bar => 5 },
?> ]
=> [{:bar=>2, :foo=>"foo"}, {:bar=>3, :foo=>"foo"}, {:bar=>5, :foo=>"foo"}]

>>  a.sort {|x,y| y[:bar]<=>x[:bar]}
=> [{:bar=>5, :foo=>"foo"}, {:bar=>3, :foo=>"foo"}, {:bar=>2, :foo=>"foo"}]
6
ответ дан 23 November 2019 в 02:24
поделиться

Вы можете сделать:

a.sort{|a,b| b[:bar] <=> a[:bar]}
52
ответ дан 23 November 2019 в 02:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: