Assuming a stable sorting algorithm, sort twice is an option:
irb(main):001:0> [1, 0].sort.sort_by{|n| n.zero? ? 1 : 0}
=> [1, 0]
Sorting twice only to make the block to sort simpler does not sound like
a good operation.
Especially the to_s version
Error: Your application used more memory than the safety cap of 500m.
Specify -J-Xmx####m to increase it (#### = cap size in MB).
Specify -w for full OutOfMemoryError stack trace
require 'benchmark'
Infinity = 1.0/0.0
Benchmark.bm(25) do |b|
a = (1..500000).map{|n| rand(10) - 20}
b.report("A") {
a.sort.sort_by{|n| n.zero? ? 1 : 0}
}
b.report("B") {
a.sort_by {|x| x == 0 ? Infinity : x }
}
b.report("C") {
max = a.max + 1
a.sort_by {|x| x == 0 ? max : x }
}
b.report("D") {
tmp = a.partition{|x| x != 0 }
tmp[0].sort + tmp[1]
}
b.report("E") {
a.sort do |x,y|
case
when x == 0 then 1
when y == 0 then -1
else x <=> y
end
end
}
end
Linux 2.6.28-11-generic #42-Ubuntu SMP Fri Apr 17 01:57:59 UTC 2009
i686 GNU/Linux
ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]
user system total real
A 1.070000 0.160000 1.230000 ( 1.320943)
B 1.290000 0.140000 1.430000 ( 1.691468)
C 1.530000 0.200000 1.730000 ( 2.863440)
D 0.750000 0.180000 0.930000 ( 1.323304)
E 3.840000 0.400000 4.240000 ( 5.043411)
ruby 1.9.0 (2008-06-20 revision 17482) [i486-linux]
user system total real
A 0.470000 0.020000 0.490000 ( 0.522487)
B 0.550000 0.010000 0.560000 ( 0.631449)
C 0.640000 0.000000 0.640000 ( 0.692639)
D 0.230000 0.020000 0.250000 ( 0.279466)
E 0.820000 0.000000 0.820000 ( 0.870455)
jruby 1.3.0 (ruby 1.8.6p287) (2009-06-03 5dc2e22) (OpenJDK Client VM
1.6.0_0) [i386-java]
user system total real
A 1.664000 0.000000 1.664000 ( 1.617000)
B 2.315000 0.000000 2.315000 ( 2.316000)
C 2.536000 0.000000 2.536000 ( 2.536000)
D 0.772000 0.000000 0.772000 ( 0.772000)
E 5.175000 0.000000 5.175000 ( 5.175000)