首页 > 解决方案 > 嵌套字典导航

问题描述

我在 Ruby 中有一个嵌套的字典/哈希结构,如下所示:

d = {
 :foo => {
   :hoo => nil,
   :baz => {
     # ...
   },
 },

 :bar => {
   :doo => { 
      # ...
   },
   :loo => nil, 
 },

 # ...
}

每个单独的字典的大小都未知。它的键是符号,它的值是或者是nil另一个字典。我正在尝试编写两种方法:

  1. down()将当前字典和有效键作为参数并返回指向该值的指针(nil 或另一个字典)。
  2. up()获取当前字典并返回指向它所在的外部字典的指针。

down()很简单(它与 相同d[:foo]),但我很犹豫是否只使用d[:foo],因为如果不存储一些关于as的up()额外结构/导航信息,基本上是不可能的。ddown()

返回值不能是 中任何内容的副本d,它们必须是指针。我仍然对 Ruby 中哪些情况是按值传递与按引用传递感到困惑,但我确实知道它的所有“有效指针”变量都是可变的。

更新:

当我说“使用当前字典”时,我只是指一些变量dict,例如dict = dor dict = (some child of d)dict是字典或 nil。例如:

d = # ...

dict = down(d, :foo)
# dict is now the current dictionary and points to {:hoo=>nil,:baz=>{}} in d

dict2 = down(dict, :baz)
# down() "takes the current dictionary" (dict) 
# then returns a new current dictionary (dict2)

在我尝试解决方案时,一些额外的实体跟踪当前字典所在的级别似乎很重要。

标签: rubydictionarypointers

解决方案


我不确定我是否完全理解了这个问题,但也许您正在寻找类似以下的内容,它只是一个链表,而不是字典的嵌套哈希,但我认为这更典型地体现在 Ruby 中。

class Dictionary
  attr_accessor :name, :up, :down
  def initialize(name, up)
    @name = name
    @up = up
    @down = []
    up.down << self unless up.nil?
  end
end

我们首先创建顶级字典。

top = Dictionary.new("top", nil)
  #=> #<Dictionary:0x000056dd361bcd48 @name="top", @up=nil, @down=[]>

现在让我们创建一个top.

top_foo = Dictionary.new("foo", top)
  #=> #<Dictionary:0x000056dd361ce458 @name="foo",
  #     @up=#<Dictionary:0x000056dd361bcd48 @name="top", @up=nil,
  #       @down=[#<Dictionary:0x000056dd361ce458 ...>]>,
  #     @down=[]>

仔细查看返回值。top_foo的实例变量的值@upDictionary命名的实例top。我们可以更清楚地看到这一点:

top_foo.up.name
  #=> "top"
top_foo.down
  #=> []

让我们看看top.down(以前是一个空数组)是如何变化的。

top.down.map(&:name)
  #=> ["foo"]

现在创建top.

top_goo = Dictionary.new("goo", top)
  #=> #<Dictionary:0x000056dd3611a480 @name="goo",
  #     @up=#<Dictionary:0x000056dd35eed180 @name="top",...
  #     @down=[]> 
top_goo.up.name
  #=> "top" 
top_goo.down
  #=> [] 

top.down.map(&:name)
  #=> ["foo", "goo"]

现在创建一个孩子top_foo

top_foo_who = Dictionary.new("who", top_foo)
  #=> #<Dictionary:0x000056dd36171488 @name="who",
  #     @up=#<top_foo instance>

top_foo_who.name
  #=> "who"
top_foo_who.up.name
  #=> "foo"
top_foo_who.down
  #=> []

top_foo.down.map(&:name)
  #=> "foo"

假设我们希望从top_foo_whotop

start = top_foo_who
dict = loop do
  break start if start.up.nil?
  start = start.up
end
  #=> #<Dictionary:...> 

dict.name
  #=> "top" 
dict.down.map(&:name)
  #=> ["foo", "goo"] 

如果我们想从toptop_foo,按名称"foo",我们可以这样写:

idx = top.down.map(&:name).index("foo")
  #=> 0
dict = top.down[idx]      
  #=> #<Dictionary...>
dict.name
  #=> "foo"

推荐阅读