Reputation: 5603
I have an array:
[1,2,3,4,5,6,7,8,9,10]
and I need to count three separate things.
1) All values less than or equal to 6
.
2) All values equal to 7
or 8
.
3) All values greater than 8
.
What is the best way to do this without counting individual values and adding them all together?
Upvotes: 1
Views: 2446
Reputation: 110675
More interesting, imo, is to answer @Luigi's three questions with a single statement (containing no semicolons). Here are two ways to do it:
a = [1,2,3,4,5,6,7,8,9,10]
a.inject([0,0,0]) {|arr,i| [arr[0]+(i<7 ? 1:0), arr[1]+((i>6 and i<9) ? 1:0), arr[2]+(i>8 ? 1:0)]}
a.slice_before(7).to_a.map {|arr| arr.slice_before(9).to_a}.flatten(1).map(&:size)
# => [6, 2, 2]
Edit: another, inspired by @staafl's answer:
arr.group_by {|e| (e+1)/2-4<=>0}.values.map(&:size)
Can you suggest others?
Upvotes: 0
Reputation: 3225
How about this:
>> hash = Hash.new(0)
>> arr = [1,2,3,4,5,6,7,8,9,10]
>> arr.each { |e| hash[(e-7.5).truncate<=>0]+=1 }
>> hash
=> {-1=>6, 0=>2, 1=>2}
Or even more succinct:
>> arr = [1,2,3,4,5,6,7,8,9,10]
>> arr.each_with_object(Hash.new(0)) { |e,h| h[(e-7.5).truncate<=>0]+=1 }
=> {-1=>6, 0=>2, 1=>2}
Upvotes: 0
Reputation: 26193
arr = [1,2,3,4,5,6,7,8,9,10]
arr.select {|e| e <= 6}.size
#=> 6
arr.select {|e| e == 7 || e == 8}.size
#=> 2
arr.select {|e| e > 8}.size
#=> 2
Upvotes: 1
Reputation: 33370
Use Enumerable#count with a block.
[1,2,3,4,5,6,7,8,9,10].count { |val| val <= 6 }
[1,2,3,4,5,6,7,8,9,10].count { |val| val == 7 || val == 8 }
[1,2,3,4,5,6,7,8,9,10].count { |val| val > 8 }
Upvotes: 3