【问题标题】:Ruby seem to reference a variable instead of coping it's valueRuby 似乎引用了一个变量而不是处理它的值
【发布时间】:2012-09-19 19:55:58
【问题描述】:

为什么我的 data_dummy 哈希值增加了?我想用它来启动另一个零值的哈希!

fau[f.label][:hash] = data_dummy #  ==>{"name 1" => 0, "name 2" => 0} but in the second loop it contains data from the first loop e.g. {"name 1" => 2, "name 2" => 0}

当使用字符串而不是变量 dummy_data 时,代码按预期工作。

fau[f.label][:hash] = {"name 1" => 0, "name 2" => 0} 

我不能这样做,因为“名字 X”正在改变......

这对我来说很奇怪!

完整代码

fau = {}
series = []
labels = [{:value => 0, :text => ''}]

data_dummy = {}
source.each do |c|
  data_dummy[c.name] = 0
end
i = 0
data_dummy.each do |k,v|
  i += 1
  labels.push({:value => i, :text => k})
end

source.each do |s|
  logger.debug "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
  logger.debug "Source: '#{s.name}'|'#{fault_labels[s.fault_id.to_s].label}' => #{s.cnt}"
  con_name = s.name #TODO: Cut name (remove location like left,right, ...)
  f = fault_labels[s.fault_id.to_s]
  unless fau.has_key?(f.label)
    # init faults-hash 'fau'
    fau[f.label] = {:total => 0, :hash => {}, :color => f.color, :name => f.label} #, :data => []
    # add all connector_names as keys with value = 0
    logger.debug "init :hash with #{data_dummy}" #  ==>{"name 1" => 0, "name 2" => 0} but in the second loop it contains data from the first loop e.g. {"name 1" => 2, "name 2" => 0}
    fau[f.label][:hash] = data_dummy
    # this way the number of incidents are all in the same order for each fault (first dimension key)
    # and all get at least a value of 0
 end
  logger.debug "Count up fau['#{f.label}'][:total] = #{fau[f.label][:total]} + #{s.cnt} (where connector '#{s.name}' and fault '#{f.label}')"
  logger.debug "Count up fau['#{f.label}'][:hash]['#{con_name}'] = #{fau[f.label][:hash][con_name]} + #{s.cnt}"
  fau[f.label][:total] += s.cnt
  fau[f.label][:hash][con_name] += s.cnt
  logger.debug "result :hash with #{fau[f.label][:hash].inspect}}"
end

【问题讨论】:

    标签: ruby ruby-on-rails-3.2


    【解决方案1】:

    因为 Ruby 哈希和所有 Ruby 对象一样,都是引用和复制一个,例如 hash2 = hash1 只会创建引用的副本。修改hash2会修改hash1,实际上它们只是同一事物的不同别名。

    您想改用克隆方法。

    hash2 = hash1.clone

    另见How do I copy a hash in Ruby?

    请注意,即使这样也只会创建浅拷贝,如果您有嵌套哈希(例如myhash = {"key1" => "value1", "key2" => {"key2a" => "value2a"}}),则必须进行深拷贝。根据Wayne Conrad's answer上面的问题,这样做的方法是这样的:

    def deep_copy(o)
      Marshal.load(Marshal.dump(o))
    end
    

    【讨论】:

    • 它们都是引用,只是你不会注意到数字和符号之类的东西,因为它们是不可变的。
    • 我不知道 Ruby 引用 - 我真丢脸 ;-) 谢谢!使用 .clone 现在一切正常!
    【解决方案2】:

    如果要复制哈希,需要使用dup方法:

    foo = {"name 1" => 0, "name 2" => 0}
    bar = foo
    foo["name 2"] += 1
    foo
    => {"name 2"=>1, "name 1"=>0}
    bar
    => {"name 2"=>1, "name 1"=>0}
    
    baz = foo.dup
    foo["name 2"] += 1
    foo
    => {"name 2"=>2, "name 1"=>0}
    baz
    => {"name 2"=>1, "name 1"=>0}
    

    【讨论】:

      猜你喜欢
      • 2017-11-20
      • 1970-01-01
      • 2021-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-19
      相关资源
      最近更新 更多