2012-09-27 58 views
2

爲什麼我的data_dummy哈希值會增加?我想用它來啓動另一個零值散列!Ruby似乎引用一個變量而不是應對它的值

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 

回答

5

由於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 
+2

他們」所有引用,你只是不注意像數字和符號的東西,因爲它們是不可變的。 –

+0

我不知道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} 
+0

非常感謝!它工作正常! –

+0

這是正確的答案 –

相關問題