2012-07-31 68 views
7

我試圖根據各個值落在一個範圍內的位置將一個整數數組分組爲一個散列。基本上我想要將數組轉換爲固定寬度的直方圖。Ruby Array to Histogram:如何按範圍對數字進行分組?

實施例:

values = [1,3,4,4,4,4,4,10,12,15,18] 
bin_width = 3 

我被它們落入3單位寬桶像這樣數組值成基於範圍的historgram需要組:

{'0..2'=>[1,3],'3..5'=>[4,4,4,4,4],'6..8'=>[],'9..11'=>[10].... 

是有一個簡單的一行解決方案(可能類似於values.group_by{|x| #range calc})可以在這裏工作?

+1

問題:1)我想3應該是3..5。 2)爲什麼使用字符串而不是真正的範圍?3)你還需要空的範圍? – tokland 2012-07-31 14:16:10

+3

應該沒有癡迷寫單行。爭取只涉及表達式的解決方案(就是這樣,使用功能性方法)是的,擔心任務可以節省幾條線,不。 – tokland 2012-07-31 14:30:07

回答

10
values = [1, 7, 2, 8, 2] 
values.group_by { |x| x/3 }.map { |k, vs| [(3*k..3*k+2), vs] }.to_h 
#=> {0..2=>[1, 2, 2], 6..8=>[7, 8]} 

如果你真的需要空的範圍內,我不認爲一個乾淨的班輪是可能的。但是,這應該做的:

grouped = values.group_by { |x| x/3 } 
min, max = grouped.keys.minmax 
(min..max).map { |n| [(3*n..3*n+2), grouped.fetch(n, [])] }.to_h 
#=> {0..2=>[1, 2, 2], 3..5=>[], 6..8=>[7, 8]} 
+0

哈,我只是想建議一些不需要Facets的東西,然後你更新了你的帖子。 – 2012-07-31 14:16:12

+1

@邁克爾,對不起,實際上我的方面片段完全錯誤,map_by在這裏沒有用,我們需要處理鍵,而不是數值。這就是你如何寫它? – tokland 2012-07-31 14:17:00

4

我想出了一個效率相當低的,但很明確的解決方案:

ranges = 0.step(values.max, bin_width).each_cons(2).map { |s, e| Range.new(s, e, true) } 
values.group_by { |v| ranges.find { |r| r.cover? v } } 
+0

感謝使用3單元垃圾箱的更一般版本,並且可以適應更多任意的情況。正是我需要的。 – slothbear 2017-04-16 02:28:55