我有多个具有以下两个哈希表的类。两个映射都必须具有相同的密钥集。我的问题是有很多类具有这种结构,并且密钥集会随着时间而改变。
mapping_1 = {
:key_1 => "attr_1_1",
:key_2 => "attr_2_1",
:key_3 => "attr_3_1"
}
mapping_2 = {
:key_1 => "attr_1_2",
:key_2 => "attr_2_2",
:key_3 => "attr_3_2"
}
我需要能够访问给定两个映射的键的值以及映射1的值中的键。换句话说,我需要能够执行这些操作:
mapping_1[:key_1]
mapping_1.index("attr_2_1") #(Ruby 1.8.7)
mapping_2[:key_3]
问题:有没有办法让我不必复制两种结构中的密钥?
我想过将数据映射到数组(:key_1 => ["attr_1_1", "attr_1_2"]
),但这不起作用,因为当我运行命令mapping_1.index()
时,我不知道第二个属性的值是什么
答案 0 :(得分:1)
我认为你应该创建自己的哈希类并使用它代替Hash
。它会处理密钥集,并包装每个对象的存储空间。
它可以使用类方法来编辑您的密钥集,例如:
def self.add_key(key, default_value)
def self.remove_key(key)
和您将在容器类中使用的实例方法,它们将模仿Hash
方法:
def get(key)
def set(key, value)
def find_key(value)
等。当然,您可以使用普通Hash
作为底层存储。如果您需要在向任何实例添加新密钥时扩展密钥集,只需从add_key
致电set
。
答案 1 :(得分:1)
您可以使用下面的a
之类的多维数组。 Ruby的数组方法将允许您执行所需的操作。我使用find_all
,甚至可能更直接。
irb(main):049:0> a
=> {"key1"=>["attr1_a", "attr1_b"], "key2"=>["attr2_a", "attr2_b"]}
irb(main):050:0> a['key2']
=> ["attr2_a", "attr2_b"]
irb(main):051:0> a.keys
=> ["key1", "key2"]
irb(main):052:0> a.keys.find_all{|k| a[k].include?('attr2_b')}
=> ["key2"]
当然,如果您像其他海报一样制作了自己的课程,那么您可以创建一种方法来进行搜索,例如a.key_containing('attr2_b')
而不是上面有点凌乱的find_all
字符串
答案 2 :(得分:1)
试用Multimap:https://github.com/josh/multimap。它允许每个键具有多个值并具有索引操作。请参阅此处,例如:https://github.com/josh/multimap/blob/master/lib/multimap.rb。
# call-seq:
# map.index(value) => key
#
# Returns the key for a given value. If not found, returns
# <tt>nil</tt>.
#
# map = Multimap["a" => 100, "b" => [200, 300]]
# map.index(100) #=> "a"
# map.index(200) #=> "b"
# map.index(999) #=> nil
def index(value)
invert[value]
end
答案 3 :(得分:1)
另一种方法:
SET_OF_KEYS = [:key_1, :key_2, :key_3]
Mapping = Struct.new( *SET_OF_KEYS )
class Mapping
def index(value)
kv = self.each_pair.detect{|k,v| v == value }
kv.nil? ? nil : kv.first
end
end
mapping_1 = Mapping.new("attr_1_1", "attr_2_1", "attr_3_1")
mapping_2 = Mapping.new("attr_1_2", "attr_2_2", "attr_3_2")
p mapping_1[:key_1] #=> "attr_1_1"
p mapping_1.index("attr_2_1") #=> :key_2
p mapping_2[:key_3] #=> "attr_3_2"
答案 4 :(得分:0)
创建一个模块并将其包含在相关的类中。
module MapHandeling
def [] key; @map ||= {}; @map[key] end
def []= key, value; @map ||= {}; @map[key] = value end
def index key; @map ||= {}; @map.index(key) end
end
或
module MapHandeling
def initialize map; @map = map end
def [] key; @map[key] end
def []= key, value; @map[key] = value end
def index key; @map.index(key) end
end
A级;包括MapHandeling结束
a = A.new(some_hash)
a[:key1] = :attr1
a[:key1] #=> :attr1
a.index(:attr1) = :key1