什么是这个类似哈希/树状的构造?

时间:2010-06-05 04:43:22

标签: ruby hash tree computer-science construct

我想创建一个在散列和树之间起作用的“Config”类。它只是用于存储全局值,它可以具有上下文。

以下是我如何使用它:

Config.get("root.parent.child_b") #=> "value"

以下是该课程的样子:

class Construct

  def get(path)
    # split path by "."
    # search tree for nodes
  end

  def set(key, value)
    # split path by "."
    # create tree node if necessary
    # set tree value
  end

  def tree
    {
      :root => {
        :parent => {
          :child_a => "value",
          :child_b => "another value"
        },
        :another_parent => {
          :something => {
            :nesting => "goes on and on"
          }
        }
      }
    }
  end

end

Hash和Tree(不是计算机科学专业)之间是否有这种名称的名称?基本上是树的类似哈希的接口。

像这样输出的东西:

t = TreeHash.new
t.set("root.parent.child_a", "value")
t.set("root.parent.child_b", "another value")

所需的输出格式:

t.get("root.parent.child_a") #=> "value"
t.get("root") #=> {"parent" => {"child_a" => "value", "child_b" => "another value"}}

而不是:

t.get("root") #=> nil

或者这(通过调用{}.value获得价值)

t.get("root") #=> {"parent" => {"child_a" => {}, "child_b" => {}}}

5 个答案:

答案 0 :(得分:9)

您可以在任何时间实施一个:

class TreeHash < Hash
  attr_accessor :value

  def initialize
    block = Proc.new {|h,k| h[k] = TreeHash.new(&block)}
    super &block
  end

  def get(path)
    find_node(path).value
  end

  def set(path, value)
    find_node(path).value = value
  end

private

  def find_node(path)
    path.split('.').inject(self){|h,k| h[k]}
  end
end

您可以通过将不需要的Hash方法设置为私有方法来改进实现,但它已经按照您希望的方式工作。数据存储在哈希中,因此您可以轻松地将其转换为yaml。

<小时/> 修改

为了满足进一步的期望(并且默认情况下正确转换to_yaml),您应该使用修改后的版本:

class TreeHash < Hash
  def initialize
    block = Proc.new {|h,k| h[k] = TreeHash.new(&block)}
    super &block
  end

  def get(path)
    path.split('.').inject(self){|h,k| h[k]}
  end

  def set(path, value)
    path = path.split('.')
    leaf = path.pop
    path.inject(self){|h,k| h[k]}[leaf] = value
  end
end

此版本略有权衡,因为您无法在非叶子节点中存储值。

答案 1 :(得分:1)

我认为结构的名称实际上是嵌套哈希,问题中的代码是javascript词典的重新发明。由于JS(或Python或...)中的字典可以嵌套,因此每个值可以是另一个字典,它具有自己的键/值对。在javascript中,这都是一个对象。

最好的一点是能够使用JSON整齐地定义它并传递它:

tree : {
  'root' : {
    'parent' : {
      'child_a' : "value",
      'child_b' : "another value"
    },
    'another_parent' : {
      'something' : {
        'nesting' : "goes on and on"
      }
    }
  }
};

在JS中,您可以执行tree.root.parent.child_a。

This answer to another question建议使用Hashie gem将JSON对象转换为Ruby对象。

答案 2 :(得分:0)

我认为这类似于一个类似于Java描述的here的TreeMap数据结构。它执行相同的操作(键/值映射),但检索可能会有所不同,因为您使用节点本身作为键。从描述的TreeMap中检索是从实现中抽象出来的,因为当你传入一个键时,你不知道它在树中的确切位置。

希望有意义!

答案 3 :(得分:0)

呃......当然可以使用分层哈希表来完成,但为什么需要层次结构呢?如果您只需要精确匹配的get和put,为什么不能只使用一个使用点分隔命名约定的哈希表?

这就是实现您所要求的功能所需要的,而且显然非常简单......

答案 4 :(得分:0)

为什么要使用类似哈希的界面?为什么不使用链接方法来导航树?例如config.root.parent.child_b并使用实例方法,如果需要method_missing()来实现它们?