2011-03-31 15 views
3

我有多个具有以下两个哈希表的类。这两种映射必须具有相同的一组密钥。我的问题是,这个结构有很多类,并且键集会随着时间而改变。创建数据结构而不复制密钥

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()我不知道第二个属性的值是什么。

回答

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作为底层存储。如果您需要在每次向任何实例添加新密钥时扩展您的密钥集,请致电set拨打add_key

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串上述

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 
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 
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"