proposal: Hash#deep_set

When we want to set value in nested Hash the code become longer, I’d like to have similar to Hash#dig but for setting values

example:

users_hash = {} users.each do |user| country_code = user.country&.code users_hash[country_code] ||= {} users_hash[country_code][user.city] ||= {} users_hash[country_code][user.city][user.email] = user end 

With Hash#deep_set (or other better name) it could be

users_hash = {} users.each do |user| users_hash.deep_set( [user.country&.code, user.city, user.email] => user ) # or users_hash.deep_set(user.country&.code, user.city, user.email, with: user) # users_hash.deep_hash(user.country&.code, user.city)[user.email] = user # or users_hash.deep_set_array(user.country&.code, user.city, with: user) end 

Also, can override :[]= method to support multiple arguments

... def []=(*args, **kargs) # make deep set end ... users_hash = HashWithDeepSet.new # or {}.with_deep_set users.each do |user| users_hash[user.country&.code, user.city, user.email] = user # or users_hash[user.country&.code, user.city, fill_with: []] << user end 

some other useful methods I copy from project to project, mostly for large arrays to make lookup faster

def map_by_key(array, key) result = {} array.each do |element| result[element[key]] ||= [] result[element[key]] << element end result end def uniq_map_by_key(array, key) result = {} array.each do |element| result[element[key]] = element end result end 

This seems to have similarity with this previous proposal. As suggested on that discussion, using the default_proc functionality of Ruby to auto-create nested hashes seems to offer similar benefits without anything new.

As to your map_by_key that seems to be doing the same thing as Ruby built-in group_by function. And your uniq_map_by_key seems like the same as the ActiveSupport’s built-in index_by function.