【问题标题】:Ruby key getting replaced, instead of a new key createdRuby 密钥被替换,而不是创建新密钥
【发布时间】:2019-11-13 08:22:46
【问题描述】:
ruby 2.5

我有以下代码:

test = {'primer' => 'grey'}
layers = ["tan","burgundy"]
fillers = ["blue","yellow"]
layers.each do |l|
    fillers.each do |f|
      test[l] = {} if !test.respond_to?(l)
      test[l][f] = {} if !test[l].respond_to?(f)
    end
end

当我在 irb 中运行它时,我得到以下信息:

{"primer"=>"grey", "tan"=>{"yellow"=>{}}, "burgundy"=>{"yellow"=>{}}}

我期待:

{"primer"=>"grey", "tan"=>{"blue"=>{},"yellow"=>{}}, "burgundy"=>{"blue"=>{},"yellow"=>{}}}

为什么第一个respond_to产生密钥,而第二个代替前一个密钥?

我错过了什么?

【问题讨论】:

    标签: ruby hash ruby-2.5


    【解决方案1】:

    表达式

    test.respond_to?(l)
    

    没有意义。 l 是一个字符串,respond_to? 如果接收者有一个由这个字符串表示的名称的方法,则返回 true。由于接收者是一个Hash,而一个Hash没有Hash#tan和Hash#burgundy方法,所以测试总是会失败。

    也许你想改用test.has_key?(l)....

    【讨论】:

    • 我的问题是为什么它响应第一个 respond_to 而不是下一个
    • 所有 respond_to 将返回 false,因此 if 子句将始终为 true。最终结果与您根本没有编写 if 子句相同。这就是为什么你得到你的结果。如果您在每次分配给test 哈希后放置一个p test,您可以轻松验证它。
    • @EastsideDeveloper :换句话说:实际上,您执行layers.each { |l| fillers.each { |f| test[l] = {}; test[l][f] = {} }},您的输入数据将导致{"primer"=>"grey", "tan"=>{"yellow"=>{}}, "burgundy"=>{"yellow"=>{}}}
    • 是的,我现在可以看到这是怎么回事了
    【解决方案2】:

    假设您有哈希{a: 1},拥有一个键:a 不会使哈希对象响应:ahash.respond_to?(:a) 仍会返回 false。你想检查一个键是否存在,这可以使用has_key?/key?来完成。

    layers.each do |l|
      fillers.each do |f|
        test[l] = {} unless test.has_key?(l)
        test[l][f] = {} unless test[l].has_key?(f)
      end
    end
    

    但是,由于您将值设置为哈希值,这是一个真实值。你也可以使用||=,它只在当前值是假的时才分配一个值。 test[:non_existing_key] 将导致 nil(除非设置了默认值)。

    上面的意思可以换成:

    layers.each do |l|
      fillers.each do |f|
        test[l] ||= {}
        test[l][f] ||= {}
      end
    end
    

    您可以使用 product 来简化整个语句,它为您组合了两个循环。

    layers.product(fillers) do |layer, filler|
      test[layer] ||= {}
      test[layer][filler] ||= {}
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-16
      • 1970-01-01
      • 1970-01-01
      • 2021-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多