这种类似哈希/树的结构叫什么?

发布于 2024-09-04 06:58:33 字数 1301 浏览 9 评论 0原文

我想创建一个介于哈希和树之间的“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" => {}}}

I want to create a "Config" class that acts somewhere between a hash and a tree. It's just for storing global values, which can have a context.

Here's how I use it:

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

Here's what the class might look like:

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

Is there a name for this kind of thing, somewhere between Hash and Tree (not a Computer Science major)? Basically a hash-like interface to a tree.

Something that outputs like this:

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

desired output format:

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

instead of this:

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

or this (which you get the value from by calling {}.value)

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

长梦不多时 2024-09-11 06:58:33

您可以立即实现一个:

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 方法设置为私有方法来改进实现,但它已经按照您想要的方式工作了。数据以 hash 形式存储,因此您可以轻松将其转换为 yaml。


EDIT:

为了满足进一步的期望(并且默认情况下正确转换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

此版本是轻微的权衡,因为您无法在非叶节点中存储值。

You can implement one in no-time:

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

You could improve implementation by setting unneeded Hash methods as a private ones, but it already works the way you wanted it. Data is stored in hash, so you can easily convert it to yaml.


EDIT:

To meet further expectations (and, convert to_yaml by default properly) you should use modified version:

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

This version is slight trade-off, as you cannot store values in non-leaf nodes.

剧终人散尽 2024-09-11 06:58:33

我认为该结构的名称实际上是一个嵌套哈希,问题中的代码是对 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 。

另一个问题的答案建议使用Hashie gem 将 JSON 对象转换为 Ruby 对象。

I think the name for the structure is really a nested hash, and the code in the question is a reinvention of javascript's dictionaries. Since a dictionary in JS (or Python or ...) can be nested, each value can be another dictionary, which has its own key/val pairs. In javascript, that's all an object is.

And the best bit is being able to use JSON to define it neatly, and pass it around:

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

In JS you can then do tree.root.parent.child_a.

This answer to another question suggests using the Hashie gem to convert JSON objects into Ruby objects.

定格我的天空 2024-09-11 06:58:33

I think this resembles a TreeMap data structure similar to the one in Java described here. It does the same thing (key/value mappings) but retrieval might be different since you are using the nodes themselves as the keys. Retrieval from the TreeMap described is abstracted from the implementation since, when you pass in a key, you don't know the exact location of it in the tree.

Hope that makes sense!

公布 2024-09-11 06:58:33

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

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

Er... it can certainly be done, using a hierarchical hash table, but why do you need the hierarchy? IF you only need exactly-matching get and put, why can't you just make a single hash table that happens to use a dot-separated naming convention?

That's all that's needed to implement the functionality you've asked for, and it's obviously very simple...

回首观望 2024-09-11 06:58:33

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

Why use a hash-like interface at all? Why not use chaining of methods to navigate your tree? For example config.root.parent.child_b and use instance methods and if needed method_missing() to implement them?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文