我需要組數組值成紅寶石基於範圍的直方圖...Ruby Array to Histogram。如何按範圍分組數字?
values = [ 139, 145, 149, 151, 152, 153, 163, 166, 169 ]
例如:
141 - 145 = 2
146 - 150 = 1
151 - 155 = 3
...
有沒有一種簡單的方法來使用group_by
?
我需要組數組值成紅寶石基於範圍的直方圖...Ruby Array to Histogram。如何按範圍分組數字?
values = [ 139, 145, 149, 151, 152, 153, 163, 166, 169 ]
例如:
141 - 145 = 2
146 - 150 = 1
151 - 155 = 3
...
有沒有一種簡單的方法來使用group_by
?
準備直方圖一個正常指定第一個範圍的最小值,範圍大小和數量範圍。一些數據的預處理可能是確定這些值所必需的。例如,給定
values = [139, 145, 149, 151, 152, 153, 164, 166, 169]
group_size = 5
我們可以按如下計算第一組的最小值和組數:
smallest, largest = values.minmax
#=> [139, 169]
start = group_size*(smallest/group_size)
#=> 135
nbr_groups = ((largest-start+1)/group_size.to_f).ceil
#=> 7
現在,我們可以構造一個數組,我們可以用它來創建直方圖。
def group_values(values, start, nbr_groups, group_size)
groups = Array.new(nbr_groups) do |i|
f = start + i * group_size
{ nbr: 0, range: f..f+group_size-1 }
end
values.each_with_object(groups) { |v,arr|
arr[(v-start)/group_size][:nbr] += 1 }
end
讓我們試一下(爲start
和nbr_groups
上面計算的值)。
freq = group_values(values, start, nbr_groups, group_size)
#=> group_values(values, 135, 7, 5)
#=> [{:nbr=>1, :range=>135..139},
# {:nbr=>0, :range=>140..144},
# {:nbr=>2, :range=>145..149},
# {:nbr=>3, :range=>150..154},
# {:nbr=>0, :range=>155..159},
# {:nbr=>1, :range=>160..164},
# {:nbr=>2, :range=>165..169}]
注意
:range
對所得陣列的每個元素的值。groups
,以便返回的數組中包含不包含values
(對於值140-144
和155-159
)的元素的組。如果我在飛行中構建這個陣列,那麼它將不會包含這兩個組的哈希值。freq.map { |h| h[:nbr] }.minmax
#=> [0, 3]
既然你爲每個範圍一個簡單的定義處理,然後是:
values.group_by do |v|
(v-1)/5
end.values
# => [[139], [145, 149], [151, 152, 153], [163], [166, 169]]
通常group_by
包括分組元素,太多,但可以在這種情況下,它不是有用忽視。
你可以變成你要找的這個使用範圍,形式是:
values.group_by do |v|
(v-1)/5
end.map do |v, a|
[ (v*5+1..v*5+5), a.length ]
end.to_h
# => {136..140=>1, 141..145=>1, 146..150=>1, 151..155=>3, 161..165=>1, 166..170=>2}