Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
multikey_hash.rb
class MultikeyHash
include Enumerable
def initialize(initial_values = nil)
@outer_hash = {}
@inner_hash = {}
@next_inner_key = 1
if initial_values
initial_values.each do |keys, value|
if keys.is_a?(Array) && !keys.empty?
keys.each do |key|
self[key] = value
end
else
self[keys] = value
end
end
end
end
def [](outer_key)
inner_key = @outer_hash[outer_key]
if inner_key.nil?
nil
else
@inner_hash[inner_key]
end
end
def []=(outer_key, new_value)
inner_key = @inner_hash.select { |_, existing_value| existing_value == new_value }.map { |key, _| key }.first
if inner_key
@outer_hash[outer_key] = inner_key
else
@outer_hash[outer_key] = @next_inner_key
@inner_hash[@next_inner_key] = new_value
@next_inner_key += 1
end
end
def each(&block)
@outer_hash.group_by { |_, inner_key| inner_key }.inject({}) { |acc, e| acc[e.last.map { |i| i.first }] = @inner_hash[e.first]; acc }.each do |key, value|
block.call(key, value)
end
end
def inspect
"{#{self.map { |keys, value| "#{keys.inspect}=>#{value.inspect}" }.join(', ')}}"
end
def to_s
inspect
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment