2014-07-25 64 views
0

我正嘗試從[0,1]範圍內的一組數字創建直方圖。紅寶石組按範圍,數組數組?

有沒有辦法使用group_by通過數字間隔(或一些其他有趣的Ruby單行)將數組分隔成N個組/箱?

這是我目前的,無聊的,解決方法:

# values == array containing floating point numbers in the range [0,1] 

n = 10 

# EDITED from Array.new(n, 0) to Array.new(n, []), thanks emaillenin! 
histogram = Array.new(n, []) 
values.each do |val| 
    histogram[(val * n).ceil - 1].push(val) 
end 
+0

此代碼不起作用。直方圖[任何]是一個Fixnum,你不能打電話給它推動 – emaillenin

+0

@emaillenin哎呀,你是正確的!我的意思是說,是一個數組的數組,我的壞! – cjhin

+0

應該是'Array.new(n){[]}'以避免所有插槽引用相同的數組。 – tadman

回答

3

不知道你想要做什麼,但也許這會有所幫助?

values = [0.0, 0.1, 0.2, 0.3] 
values.group_by { |v| (v * 10).ceil - 1 } 

返回哈希:

{-1=>[0.0], 0=>[0.1], 1=>[0.2], 2=>[0.3]} 
+0

請記住,除了其他值('0.x')以外,如果同時存在「0.0」和「1.0」,則最多可以產生11個存儲桶。 –

+0

'group_by'完成這個很乾淨。 – tadman

1

這是做這件事。

代碼

def freq_by_bin(nbr_bins, *values) 
    nbr_bins.times.to_a.product([0]).to_h.tap { |h| 
    values.each { |v| h.update({ (v*nbr_bins).to_i=>1 }) { |_,o,_| o+1 } } } 
end 

values = [0.30, 0.25, 0.63, 0.94, 0.08, 0.94, 0.01, 
      0.41, 0.28, 0.69, 0.61, 0.12, 0.66] 
freq_by_bin(10, *values) 
    #=> {0=>2, 1=>1, 2=>2, 3=>1, 4=>1, 
    # 5=>0, 6=>4, 7=>0, 8=>0, 9=>2} 

def histogram(nbr_bins, *values) 
    h = freq_by_bin(nbr_bins, *values) 
    puts "\nfreq" 
    h.values.max.downto(0) do |n| 
    print "%2d|" % n 
    puts nbr_bins.times.with_object(' ') { |i,row| 
      row << ((h[i]==n) ? ' X ' : ' ') } 
    end 
    puts " __"+"___"*nbr_bins 
    puts nbr_bins.times.each_with_object('  ') { |i,row| row << "%2d " % i } 
end 

histogram(10, *values) 

freq 
4|      X   
3|         
2| X  X     X 
1|  X  X X     
0|     X  X X  
    ________________________________ 
     0 1 2 3 4 5 6 7 8 9 

注意

  • 有幾種方法來construc t元素爲bin=>freq的散列。使用Enumerable#group_by,您提到的和@diego使用的是一個。我使用了Hash#update(又名Hash#merge!)的形式,它佔用了一個塊。

  • 我使用Object#tap只是爲了避免需要爲初始化散列創建一個臨時(非塊)變量。