【问题标题】:Unable to create Hash of Hashes in Ruby无法在 Ruby 中创建哈希值
【发布时间】:2016-01-27 11:21:01
【问题描述】:

循环在具有某些键值对的文本文件上运行 3 次。每个循环都返回一个新的哈希,打印在下面。我想将这些哈希存储到另一个哈希中。 group1group2group3 是哈希的键:

"group1"
{
    "path"=>"/tmp/",
    "max_hits"=>262144,
    "min_hits"=>5240
}

"group2"
{
    "basic_size_limit"=>262144,
    "path"=> "/usr/bin/ruby",
    "max_hits"=>2412,
    "min_hits"=>871
}

"group3"
{
    "path"=>"/usr/tmp/",
    "basic_time_limits"=>[26214400, 26214401, 26214402],
}

我将上述哈希初始化为groups = Hash.new,而不是将它们存储到哈希哈希中。我想初始化更大的哈希值,比如group_of_groups = Hash.new{|hash, key| hash[key] = Hash.new}

group_of_groups = Hash.new{|hash, key| hash[key] = Hash.new}
Loop i in 1 .. 3
    groups = Hash.new
    ####
        Do something and add to the hash groups
    ####
    key_name = "group" + i
    group_of_groups[key_name] = groups
end Loop

但它只给我{"group1"=>{}, "group2"=>{}, "group3"=>{}}

如何解决这个问题?

【问题讨论】:

  • 尚不清楚您已经拥有哪些价值观。上面的 3 个组在单个哈希中是否作为变量?请编辑以显示更多真实的 Ruby 代码并演示这 3 个哈希的来源(我还看到 "path"= "/usr/bin/ruby" 使用不正确的运算符 = 而不是 =>
  • 这是我打印的三个不同的哈希值。我更正了= n => 的错误。我在这里放了更多信息
  • 我知道它们是 3 个不同的哈希值,但它们是存储在变量中、作为数组还是其他方式?
  • 一个循环运行了 3 次,生成了三个不同的哈希值,然后我将每个哈希值逐个放入更大的哈希值中。但是当我在循环之后打印它时,更大的哈希只打印键但没有值!其实原来的程序挺大的。
  • @DaveNewton 我正在用更多信息更新问题。

标签: ruby hash


【解决方案1】:

如果您在 3 个变量 group1、group2 和 group3 中有 3 个哈希,您可以使用这样的哈希创建哈希:

group1 = {
    "path"=>"/tmp/",
    "max_hits"=>262144,
    "min_hits"=>5240
}

group2 = {
    "basic_size_limit"=>262144,
    "path"=> "/usr/bin/ruby",
    "max_hits"=>2412,
    "min_hits"=>871
}

group3 = {
    "path"=>"/usr/tmp/",
    "basic_time_limits"=>[26214400, 26214401, 26214402],
}

group_of_groups = {"group1"=>group1, "group2"=>group2, "group3"=>group3}

# result
{
    "group1" => {
        "path"=>"/tmp/",
        "max_hits"=>262144,
        "min_hits"=>5240
    }, 
    "group2" => {
        "basic_size_limit"=>262144,
        "path"=> "/usr/bin/ruby",
        "max_hits"=>2412,
        "min_hits"=>871
    },
    "group3" => {
        "path"=>"/usr/tmp/",
        "basic_time_limits"=>[26214400, 26214401, 26214402],
    },
}

请记住,Ruby 中的所有内容都是通过引用进行的,因此修改 group_of_groups 内的哈希也会修改原始哈希。

【讨论】:

  • 您的回答给了我解决方案的提示。我实际上是在每个循环结束时清除哈希,结果它结束了,但是在通过引用传递时被从任何地方删除!!
【解决方案2】:

如果你想一次性初始化所有东西,你可以这样写:

group_of_groups = { 
    "group1" => {
        "path"=>"/tmp/",
        "max_hits"=>262144,
        "min_hits"=>5240
    },
    "group2" => {
        "basic_size_limit"=>262144,
        "path"=> "/usr/bin/ruby",
        "max_hits"=>2412,
        "min_hits"=>871
    },
    "group3" => {
        "path"=>"/usr/tmp/",
        "basic_time_limits"=>[26214400, 26214401, 26214402],
    }
}

换行符明确什么属于什么,但不是必需的。

【讨论】:

    【解决方案3】:

    除了其他答案,如果您需要以编程方式构建哈希,也可以这样做:

    group1 = {
        "path"=>"/tmp/",
        "max_hits"=>262144,
        "min_hits"=>5240
    }
    
    group2 = {
        "basic_size_limit"=>262144,
        "path"=> "/usr/bin/ruby",
        "max_hits"=>2412,
        "min_hits"=>871
    }
    
    group3 = {
        "path"=>"/usr/tmp/",
        "basic_time_limits"=>[26214400, 26214401, 26214402],
    }
    
    group_of_groups = 
        ["group1", "group2", "group3"].each_with_object({}) do |sub_hash_name, new_hash|
            new_hash[sub_hash_name] = instance_eval(sub_hash_name)
        end
    
    # Result
    {
        "group1" => {
            "path"=>"/tmp/",
            "max_hits"=>262144,
            "min_hits"=>5240
        }, 
        "group2" => {
            "basic_size_limit"=>262144,
            "path"=> "/usr/bin/ruby",
            "max_hits"=>2412,
            "min_hits"=>871
        },
        "group3" => {
            "path"=>"/usr/tmp/",
            "basic_time_limits"=>[26214400, 26214401, 26214402],
        },
    }
    

    【讨论】:

    • 在这种情况下使用 eval 是不合适或不建议的。
    • @Gravatite 因为它很脆弱——如果有人决定更改局部变量的名称,他们可能不知道要更改数组的字符串值?
    • 有两个原因。首先,Ruby 支持正确的反射,因此没有理由使用 eval 来获取变量。第二个更像是一个哲学问题,因为 eval 通常会导致各种弊端,从安全漏洞到难以诊断的错误以及各种其他问题。快速谷歌搜索应该会找到更深入的文章,了解何时适合使用 eval。
    • @Gravatite 我不确定您所说的proper reflection 是什么意思。如果我还需要使用名称,我将如何以编程方式按名称访问变量的内容?我已经知道,由于问题的模糊性,从变量的内容中访问变量的名称是不可能的,所以如果我需要访问变量的名称,我无法将变量本身放入列表中。我知道完成此操作的唯一方法是使用eval 而无需创建静态哈希。不过,您可以将上面的名单替换为 local_variables.select { |v| !x.start_with?('_').to_s }
    猜你喜欢
    • 1970-01-01
    • 2013-04-11
    • 1970-01-01
    • 2012-11-23
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    • 2015-04-19
    • 2015-03-01
    相关资源
    最近更新 更多