Das Ruby-Array erbt group_by
von Enumerable, was das schön macht:
Hash[*data.group_by{ |v| v }.flat_map{ |k, v| [k, v.size] }]
Was zurückgibt:
{
0 => 1,
1 => 1,
2 => 5,
3 => 6,
4 => 4,
5 => 2,
6 => 3,
7 => 5,
8 => 1,
9 => 2,
10 => 1
}
Das ist einfach eine saubere Hash-Funktion. Wenn Sie ein Array jedes Bins und Frequenzpaars möchten, können Sie es verkürzen und verwenden:
data = [0,1,2,2,3,3,3,4]
data.group_by{ |v| v }.map{ |k, v| [k, v.size] }
# => [[0, 1], [1, 1], [2, 2], [3, 3], [4, 1]]
Hier ist, was der Code und group_by
mit dem kleineren Datensatz machen:
data.group_by{ |v| v }
# => {0=>[0], 1=>[1], 2=>[2, 2], 3=>[3, 3, 3], 4=>[4]}
data.group_by{ |v| v }.flat_map{ |k, v| [k, v.size] }
# => [0, 1, 1, 1, 2, 2, 3, 3, 4, 1]
Wie in den Kommentaren von Telmo Costa erwähnt, führte Ruby in v2.7.0 tally
ein. Ein schneller Benchmark zeigt, dass tally
etwa 3x schneller ist:
require 'fruity'
puts "Ruby v#{RUBY_VERSION}"
data = [0,1,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,5,5,6,6,6,7,7,7,7,7,8,9,9,10]
data.group_by{ |v| v }.map{ |k, v| [k, v.size] }.to_h
# => {0=>1, 1=>1, 2=>5, 3=>6, 4=>4, 5=>2, 6=>3, 7=>5, 8=>1, 9=>2, 10=>1}
data.group_by { |v| v }.transform_values(&:size)
# => {0=>1, 1=>1, 2=>5, 3=>6, 4=>4, 5=>2, 6=>3, 7=>5, 8=>1, 9=>2, 10=>1}
data.tally
# => {0=>1, 1=>1, 2=>5, 3=>6, 4=>4, 5=>2, 6=>3, 7=>5, 8=>1, 9=>2, 10=>1}
data.group_by{ |v| v }.keys.sort.map { |key| [key, data.group_by{ |v| v }[key].size] }.to_h
# => {0=>1, 1=>1, 2=>5, 3=>6, 4=>4, 5=>2, 6=>3, 7=>5, 8=>1, 9=>2, 10=>1}
compare do
gb { data.group_by{ |v| v }.map{ |k, v| [k, v.size] }.to_h }
rriemann { data.group_by { |v| v }.transform_values(&:size) }
telmo_costa { data.tally }
CBK {data.group_by{ |v| v }.keys.sort.map { |key| [key, data.group_by{ |v| v }[key].size] }.to_h }
end
Ergebnis:
# >> Ruby v2.7.0
# >> Jeder Test wird 1024 Mal durchgeführt. Der Test dauert etwa 2 Sekunden.
# >> telmo_costa ist 2x schneller als rriemann ± 0.1
# >> rriemann ist ähnlich schnell wie gb
# >> gb ist 8x schneller als CBK ± 1.0
Also verwenden Sie tally
.