创建一个不重复键的数据结构

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

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)

等等。当然,您可以使用普通的哈希作为基础存储。如果您需要能够在向任何实例添加新键时扩展键集,请从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 字符串。

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"

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接