Bitwise
Bitwise

Reputation: 8461

Create Hash that matches keys and increments value

I have a huge array that lists the day of the week in which the object was created, so I end up with an array similar to the following:

["wednesday", "thursday", "friday"] except that it contains 250,000 elements.

What I want to make is a new hash that will match the key and increment the value, so the result is as follows:

{"wednesday": 250, "thursday": 600, "saturday": 120}

How can I get achieve this outcome?

Here is my current code:

days = []

Invitation.all.each do |invitation|
  day = invitation.created_at.strftime("%A")
  days.push(day)
end

days

Upvotes: 0

Views: 1343

Answers (4)

Aparichith
Aparichith

Reputation: 1535

If its a plain ruby Array and want to group by values

invites = ["wednesday", "thursday", "friday", "wednesday", "wednesday", "friday"]

invite_group = Hash.new(0)
invites.each { |invite| invite_group[invite] += 1 }

# invite_group => {"wednesday"=>3, "thursday"=>1, "friday"=>2}

Or by using key? method

invite_group = Hash.new
# invite_group = {}

invites.each { |invite| if invite_group.key?(invite); invite_group[invite] += 1; else invite_group[invite] = 1; end}
# # invite_group => {"wednesday"=>3, "thursday"=>1, "friday"=>2}

Upvotes: 0

Othmane El Kesri
Othmane El Kesri

Reputation: 603

array = ["wednesday", "thursday", "friday", "wednesday", "wednesday", "friday"]

days = array.each_with_object(Hash.new(0)) do |e, total| 
  total[e] += 1 
end

will give you this :

{"wednesday"=>3, "thursday"=>1, "friday"=>2}

A 'one-line' solution of your problem:

days = Invitation.pluck(:created_at).each_with_object(Hash.new(0)) do |e, total| 
  total[e.strftime("%A")] += 1 
end

Upvotes: 4

JCorcuera
JCorcuera

Reputation: 6834

If you are using postgresql, you can do the query at database level and just use Ruby to map the results:

Invitation
  .select("EXTRACT(DOW FROM created_at) AS day_of_the_week, COUNT(*) AS total_records")
  .group("day_of_the_week")
  .map {|result| [Date::DAYNAMES[result.day_of_the_week], result.total_records] }
  .to_h
#=> {"Friday"=>4, "Tuesday"=>2, "Thursday"=>5, "Monday"=>3, "Wednesday"=>5, "Saturday"=>3} 

By this way you avoid to load all the Invitation objects and just perform one query.

Upvotes: 3

max pleaner
max pleaner

Reputation: 26758

You can do it like this:

Invitation.all.reduce(Hash.new(0)) do |memo, invitation|
  memo[invitation.created_at.strftime("%A")] += 1
  memo
end

Hash.new(0) makes a hash where the default values are 0. This is a general-purpose way to get counts from an array

Upvotes: 6

Related Questions