jednorazowym przejściu przez hash gromadzić liczniki. Użyj .max(), aby znaleźć hash z największą wartością.
#!/usr/bin/ruby
a = Hash.new(0)
["1.111", "1.122", "1.250", "1.111"].each { |num|
a[num] += 1
}
a.max{ |a,b| a[1] <=> b[1] } # => ["1.111", 2]
lub toczyć je wszystkie w jednym wierszu:
ary.inject(Hash.new(0)){ |h,i| h[i] += 1; h }.max{ |a,b| a[1] <=> b[1] } # => ["1.111", 2]
Jeśli chcesz tylko dodać element do tyłu.pierwszy():
ary.inject(Hash.new(0)){ |h,i| h[i] += 1; h }.max{ |a,b| a[1] <=> b[1] }.first # => "1.111"
Pierwsza próbka Kiedyś to w jaki sposób to zrobić w Perlu zwykle. Drugi to więcej Ruby-owski. Oba działają ze starszymi wersjami Rubiego. Chciałem je porównać, a także zobaczyć, jak rozwiązanie Wayne'a by przyspieszyć więc przetestowane z benchmarkiem:
#!/usr/bin/env ruby
require 'benchmark'
ary = ["1.111", "1.122", "1.250", "1.111"] * 1000
def most_common_value(a)
a.group_by { |e| e }.values.max_by { |values| values.size }.first
end
n = 1000
Benchmark.bm(20) do |x|
x.report("Hash.new(0)") do
n.times do
a = Hash.new(0)
ary.each { |num| a[num] += 1 }
a.max{ |a,b| a[1] <=> b[1] }.first
end
end
x.report("inject:") do
n.times do
ary.inject(Hash.new(0)){ |h,i| h[i] += 1; h }.max{ |a,b| a[1] <=> b[1] }.first
end
end
x.report("most_common_value():") do
n.times do
most_common_value(ary)
end
end
end
Oto wyniki:
user system total real
Hash.new(0) 2.150000 0.000000 2.150000 ( 2.164180)
inject: 2.440000 0.010000 2.450000 ( 2.451466)
most_common_value(): 1.080000 0.000000 1.080000 ( 1.089784)
Jestem pod wrażeniem przyspieszenia w zwykły sposób, w jaki to zrobię. Dobra robota. –
@Wayne Conrad, rozwiązanie uber. +1 –
Oto krótsza wersja: x.group_by {| e | e} .values.max_by (&: size) .pierwszy # => "1.111" Włączenie go do metody, jeśli jest to pożądane, pozostawia się czytelnikowi ;-) –