Reputation: 160
I'm trying to count numbers of different values in mysql table columns. Range of possible values is integer and from 0-10. The following code is working, but I'm wondering if there is a more elegant way to do this?
# Example data from Mysql
result = [{ :column1 => "2", :column2 => "3", :column3 => "1"},{ :column1 => "2", :column2 => "3", :column3 => "1"},{ :column1 => "1", :column2 => "2", :column3 => "3"}]
# Init hash
final_result = Hash.new { |h, k| h[k] = { } }
# Loop result columns
result.each do |single_column|
# Loop single items inside columns
single_column.each do |single_result|
# Create column if does not exist
if final_result[single_result[0]][single_result[1]].nil? then
final_result[single_result[0]][single_result[1]] = 1
else
final_result[single_result[0]][single_result[1]] += 1
end
end
end
puts final_result
# => {:column1=>{"2"=>2, "1"=>1}, :column2=>{"3"=>2, "2"=>1}, :column3=>{"1"=>2, "3"=>1}}
Upvotes: 0
Views: 81
Reputation: 8212
Have a look at the active record count
method (doc link). You can use that in combination with group
to do what you are trying to achieve.
[:column1, :column2, :column3].inject({}) do |hash, column|
hash[column] = Model.group(column).count
hash
end
Upvotes: 1
Reputation: 211560
There's some room for cleaning up here. The most obvious part is that long, clunky if
statement. The test vs nil?
is pointless, remember in Ruby the only things that are logically false are false
and nil
, so since false
is never going to show up here, the test vs. nil
specifically can be removed.
More than that, though, you're on the right track with the custom Hash.new
call, but you don't go far enough. Why not initialize the second tier with zero?
That results in code that looks like:
result = [
{ :column1 => "2", :column2 => "3", :column3 => "1"},
{ :column1 => "2", :column2 => "3", :column3 => "1"},
{ :column1 => "1", :column2 => "2", :column3 => "3"}
]
# Init hash
final_result = Hash.new { |h, k| h[k] = Hash.new(0) }
# Loop result columns
result.each do |single_column|
single_column.each do |r|
final_result[r[0]][r[1]] += 1
end
end
puts final_result.inspect
Upvotes: 1