0

Ok, so 8 months into Ruby Hashes are still proving somewhat of an enigma.

I pull 10 records from the database, each with its own category field. Many of the records with share the same category, so I want them grouped by their categories in a hash.

I understand that the Key's are always unique, which is what makes a Hash a Hash. What I am struggling to do is add values to the existing key in the hash.

def self.categorise_events
    hash = {}
    self.limit(10).map do |event|
        if hash.key?(event.event_type) #check if the key already exists
            hash[event.event_type][event] #add the event record to that key
        else
            hash[event.event_type] = event #create the key if it doesn't exist and add the record 
        end
    end
    hash
end 

This is more of a gist of what I am trying to achieve. I've had other compositions which have been closer but still not quite doing it.

2 Answers 2

2

You can add to an existing hash like

hash[key] = value

but in your case, your value is a collection of values, so it's an array

hash[key] = []
hash[key] << value

so you can add to an existing group with

unless hash.key?(event.event_type)
  hash[event.event_type] = []
end

hash[event.event_type] << event

Now, this can be accomplished with the builtin method #group_by as seen on the documentations. But in your case, because it's using ActiveRecord, you can consider using #group to group records using SQL and greatly improving the performance of the grouping

self.limit(10).group(:event_type)

Check out the docs here.

Sign up to request clarification or add additional context in comments.

2 Comments

than k you, your answer helped a great deal with understanding
It's better to do hash[key] ||= [] than hash[key] = [] : the former is equivalent to hash[key] = (hash[key] || []) and will only set it to an empty array if it doesn't exist already. If you do hash[key] = [] you risk wiping out what you had in there already.
1

Key is always uniq. So if you want to add values to a key, that value should be Array.

In this situation you can use group_by. Try

hash = self.limit(10).group_by{|e| e.event_type}

It returns a Hash whose keys are event_type and values are Array of records.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.