Ruby是否将我的哈希变成了一个数组,如果是这样,为什么?

时间:2016-10-24 04:21:48

标签: ruby

所以我试图创建一个树数据结构,可以通过嵌套哈希实例化。

我的代码如下,并且应该递归地从密钥中取出节点,并将子节点从它们的值中取出。

class Tree
    attr_accessor :children, :node_name
    #def initialize(name, children=[])
    #   @children = children
    #   @node_name = name
    # end
    def initialize(hashTree)
        @node_name = hashTree.keys[0]
        @children = []
        p node_name
        hashTree[node_name].each do |hash|
            children << Tree.new(hash)
        end
    end
    #...
end

p = {'grandpa' => { 'dad' => {'child 1' => {}, 'child2' => {} }, 'uncle' => {'child 3' => {}, 'child 4' => {} } } }
p p
p Tree.new(p)

当我尝试运行该代码时,我得到以下内容:

{"grandpa"=>{"dad"=>{"child 1"=>{}, "child2"=>{}}, "uncle"=>{"child 3"=>{}, "child 4"=>{}}}}
"grandpa"
/Users/Matt/sw/sevenLang/week1/hw-tree.rb:8:in `initialize': undefined method `keys' for ["dad", {"child 1"=>{}, "child2"=>{}}]:Array (NoMethodError)
    from /Users/Matt/sw/sevenLang/week1/hw-tree.rb:12:in `new'
    from /Users/Matt/sw/sevenLang/week1/hw-tree.rb:12:in `block in initialize'
    from /Users/Matt/sw/sevenLang/week1/hw-tree.rb:11:in `each'
    from /Users/Matt/sw/sevenLang/week1/hw-tree.rb:11:in `initialize'
    from /Users/Matt/sw/sevenLang/week1/hw-tree.rb:26:in `new'
    from /Users/Matt/sw/sevenLang/week1/hw-tree.rb:26:in `<main>'
[Finished in 0.1s with exit code 1]

看起来每个人都将嵌套的哈希变成一个数组,其中键是第一个元素,值是第二个元素。

1 个答案:

答案 0 :(得分:2)

hashTree[node_name]p["grandpa"],是哈希:

{"dad"=>{"child 1"=>{}, "child2"=>{}}, "uncle"=>{"child 3"=>{}, "child 4"=>{}}}

Hash#each将产生一个双元素数组:一个键和一个值。所以,如果你写

hashTree[node_name].each do |hash|

hashTree[node_name]是一个哈希,hash将始终是一个双元素数组。由于语法上的技巧,如果有多个形式参数,Ruby将自动splat一个数组参数,所以你也可以写:

hashTree[node_name].each do |name, hash|

这不会导致错误。 (实际上你在逻辑中仍然存在无关的错误,因为你正在跳过一个级别。)

无错误版本:

class Tree
    attr_accessor :children, :node_name
    def initialize(name, hashTree)
        @node_name = name
        @children = []
        hashTree.each do |child_name, hash|
            children << Tree.new(child_name, hash)
        end
    end
end

p = {'grandpa' => { 'dad' => {'child 1' => {}, 'child2' => {} }, 'uncle' => {'child 3' => {}, 'child 4' => {} } } }
p Tree.new("Family", p)

使用map

可以缩短这一点
class Tree
    attr_accessor :children, :node_name
    def initialize(name, hashTree)
        @node_name = name
        @children = hashTree.map do |child_name, hash|
            Tree.new(child_name, hash)
        end
    end
end