Esa Mäkinen
Esa Mäkinen

Reputation: 160

Count the occurence of values in Ruby

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

Answers (2)

ReggieB
ReggieB

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

tadman
tadman

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

Related Questions