Reputation: 2170
I have an array of integers like this:
[1, 1, 1, 2, 2, 4, 4, 5, 6, 11, 11, 12, 15, 22, 23, 23, 23, 31, 32, 32]
I am trying to convert this to a hash, grouping according to ranges at intervals of 10....
So, in this case it would be
{ [1..10] => 9, [11..20] => 4, [21..30] => 4, [31..40] => 3 }
I have tried a few things which haven't come close so it's a bit pointless putting them down here. I can convert the array to ranges
[1, 1, 1, 2, 2, 4, 4, 5, 6, 11, 11, 12, 15, 22, 23, 23, 23, 31, 32, 32].sort.uniq.inject([]) do |spans, n|
if spans.empty? || spans.last.last != n - 1
spans + [n..n]
else
spans[0..-2] + [spans.last.first..n]
end
end
But this is not what I am looking for. Any suggestions?
Upvotes: 1
Views: 302
Reputation: 110675
I've modified the example to have no numbers between 21 and 30, so that the hash should include the key-value pair 21..30=>0
.
arr = [1, 1, 1, 2, 2, 4, 4, 5, 6, 11, 11, 12, 20, 32, 33, 33, 33, 41, 42, 42]
intervals = (1..arr.last-1).step(10).each_with_object({}) { |n,h| h[n..n+9] = 0 }
#=> {1..10=>0, 11..20=>0, 21..30=>0, 31..40=>0, 41..50=>0}
arr.each_with_object(intervals) do |n,intervals|
interval_end = 10*((n+9)/10)
intervals[interval_end-9..interval_end] += 1
end
#=> {1..10=>9, 11..20=>4, 21..30=>0, 31..40=>4, 41..50=>3}
Upvotes: 2
Reputation: 121000
arr.each_with_object(Hash.new(0)) do |e, hash|
i = e / 10
hash[i*10+1..i*10+10] += 1
end
#⇒ {
# 1..10 => 9,
# 11..20 => 4,
# 21..30 => 4,
# 31..40 => 3
# }
Upvotes: 3
Reputation: 44080
Hash[
your_array.group_by{|i| i / 10}.map{|k,v|
[(k*10+1..(k+1)*10), v.count]
}
]
#=> {1..10=>9, 11..20=>4, 21..30=>4, 31..40=>3}
Upvotes: 3