2011-03-31 55 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"