我有一系列哈希如下
[
{ :foo => 'foo', :bar => 2 },
{ :foo => 'foo', :bar => 3 },
{ :foo => 'foo', :bar => 5 },
]
Run Code Online (Sandbox Code Playgroud)
我试图根据:bar每个哈希值中的降序对数组进行排序.
我正在使用sort_by如下排序数组.
a.sort_by { |h| h[:bar] }
Run Code Online (Sandbox Code Playgroud)
但是,上面按升序对数组进行排序.如何按降序排序?
一种解决方案是执行以下操作:
a.sort_by { |h| -h[:bar] }
Run Code Online (Sandbox Code Playgroud)
但这个负号似乎不合适.任何意见?
the*_*Man 539
对各种建议的答案进行基准测试总是很有启发性.这是我发现的:
#!/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{...}.reverse!是最快的.在运行测试之前,我认为它会慢于" -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)
Run Code Online (Sandbox Code Playgroud)
这些是在旧的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)
Run Code Online (Sandbox Code Playgroud)
在更新的Macbook Pro上使用Ruby 2.2.1运行上述代码的新结果.同样,确切的数字并不重要,这是他们的关系:
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)
Run Code Online (Sandbox Code Playgroud)
Pab*_*dez 86
只是一个快速的事情,这表示降序的意图.
descending = -1
a.sort_by { |h| h[:bar] * descending }
Run Code Online (Sandbox Code Playgroud)
(会想到更好的方式);)
a.sort_by { |h| h[:bar] }.reverse!
Run Code Online (Sandbox Code Playgroud)
JRL*_*JRL 52
你可以这样做:
a.sort{|a,b| b[:bar] <=> a[:bar]}
Run Code Online (Sandbox Code Playgroud)
关于什么:
a.sort {|x,y| y[:bar]<=>x[:bar]}
Run Code Online (Sandbox Code Playgroud)
有用!!
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"}]
Run Code Online (Sandbox Code Playgroud)
我看到我们(除了其他人之外)基本上有两个选择:
a.sort_by { |h| -h[:bar] }
Run Code Online (Sandbox Code Playgroud)
和
a.sort_by { |h| h[:bar] }.reverse
Run Code Online (Sandbox Code Playgroud)
当排序键是唯一的时,虽然两种方法都能获得相同的结果,但是请记住,该reverse方法将颠倒等于键的顺序。
例:
a = [{foo: 1, bar: 1},{foo: 2,bar: 1}]
a.sort_by {|h| -h[:bar]}
=> [{:foo=>1, :bar=>1}, {:foo=>2, :bar=>1}]
a.sort_by {|h| h[:bar]}.reverse
=> [{:foo=>2, :bar=>1}, {:foo=>1, :bar=>1}]
Run Code Online (Sandbox Code Playgroud)
尽管您通常不需要关心这一点,但有时您会这样做。为避免这种行为,您可以引入第二个排序键(确保至少对于具有相同排序键的所有项目都必须是唯一的):
a.sort_by {|h| [-h[:bar],-h[:foo]]}
=> [{:foo=>2, :bar=>1}, {:foo=>1, :bar=>1}]
a.sort_by {|h| [h[:bar],h[:foo]]}.reverse
=> [{:foo=>2, :bar=>1}, {:foo=>1, :bar=>1}]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
209686 次 |
| 最近记录: |