I'v a hash
{1=>true, 7=>false, 6=>true, 4=>false}
or an array like
[1, true], [7, false], [6, true], [4, false]]
or
[true, false, true, false].
How can I find the number of trues in the array?
I'v a hash
{1=>true, 7=>false, 6=>true, 4=>false}
or an array like
[1, true], [7, false], [6, true], [4, false]]
or
[true, false, true, false].
How can I find the number of trues in the array?
In order to count the elements, you obviously have to iterate over the collection. Since iterating over a Hash yields two-element Arrays, the first two are actually exactly the same:
{ 1 => true, 7 => false, 6 => true, 4 => false }.count(&:last)
[[1, true], [7, false], [6, true], [4, false]].count(&:last)
For the simple Array case, you could do something like this:
[true, false, true, false].count(true)
This Array is of course also the same as the Hash#values from your Hash above, so you could use the same method on that:
{ 1 => true, 7 => false, 6 => true, 4 => false }.values.count(true)
If you don't know which one of three you will get, you could use something like this:
{ 1 => true, 7 => false, 6 => true, 4 => false }.flatten.count(true)
[[1, true], [7, false], [6, true], [4, false]].flatten.count(true)
[true, false, true, false].flatten.count(true)
With Enumerable#count:
hash.values.count(true)
array_of_pairs.map { |k, v| v }.count(true)
plain_array.count(true)
More verbose, but does not create intermediate arrays:
hash_or_array_of_pairs.inject(0) { |acc, (k, v)| acc + (v == true ? 1 : 0) }
Ruby 2.7+
Ruby 2.7 is introducing Enumerable#tally (and possibly tally_by) for this exact purpose. There's a good summary here.
There's a discussion about whether the final implementation will use tally or tally_by when providing a block, as here.
In this use case:
# or hash.tally_by if that's the accepted method for block form
hash.tally { |k, v| v }
# => { true => 2, false => 2 }
Docs on the features being released are here.
Hope this helps someone!
Simpler:
hash.values.count(true)
array.flatten.count(true)
This works with all the above cases.
Hash[array].values.count(true)One way (your hash would need .to_a called on it first for this to work on it):
[[1, true], [7, false], [6, true], [4, false]].flatten.select{|s| s == true }.size
s == true could be simplified to sI'm trying to provide a more general answer: count the amount of each element. I'm still using 2.6.6, so somebody else also has no 2.7.x.
Preparation:
values_of_hash = {1=>true, 7=>false, 6=>true, 4=>false}.values # also works with the `.map` command from the line below
values_of_array_of_pairs = [[1, true], [7, false], [6, true], [4, false]].map { |k, v| v } # or the `.inject` command from this answer: https://stackoverflow.com/a/4488905/4575793
values_of_2d = [[1, true], [7, false], [6, true], [4, false]].map(&:last) # similar idea from https://stackoverflow.com/a/4490032/4575793
values_of_2d = {1=>true, 7=>false, 6=>true, 4=>false}.map(&:last) # both a hash and an array of pairs hold the second value in `.last`
values_of_array = [true, false, true, false]
Now you can just use
def my_tally(values)
Set.new(values).map {|unique_value| [unique_value, values.count(unique_value)]}
end
# replace `_xy` with anything of the above like e.g. `_array`
my_tally values_of_xy
# => [[true, 2], [false, 2]]
That also works for arbitrary data. Maybe you want to analyse this:
values_of_xy = {1=>:banana, 2=>:cherry, 3=>:apple, 4=>:cherry, 5=>:banana, 6=>:cherry}.values
my_tally values_of_xy
# => [[:banana, 2], [:cherry, 3], [:apple, 1]]
For Ruby 2.7+, you should obviously use tally.