2010-03-31 31 views
1

我應該怎麼做marshal散列數組? 以下代碼僅打印{}如何編組散列數據?

s = Hash.new 
s.default = Array.new 
s[0] << "Tigger" 
s[7] << "Ruth" 
s[7] << "Puuh" 
data = Marshal.dump(s) 
ls = Marshal.restore(data) 
p ls 

如果散列不包含數組,它將被正確恢復。

回答

7
s = Hash.new 
s.default = Array.new 
s[0] << "Tigger" 
s[7] << "Ruth" 
s[7] << "Puuh" 

此代碼更改默認的3次(這可能是轉儲中顯示的內容),但它不會在散列中存儲任何內容。嘗試「puts s [8]」,它會返回[[「Tigger」],[「Ruth」],[「Puuh」]]。

一個Hash.default_proc會做你想要

s = Hash.new{|hash,key| hash[key]=[] } 

什麼,但你不能馬歇爾PROC。這將工作:

s = Hash.new 
s.default = Array.new 
s[0] += ["Tigger"] 
s[7] += ["Ruth"] 
s[7] += ["Puuh"] 

這工作,因爲[] + = 「跳跳虎」]創建一個新陣列。 一種替代,產生更少的陣列:

s = Hash.new 
(s[0] ||= []) << "Tigger" 
(s[7] ||= []) << "Ruth" 
(s[7] ||= []) << "Puuh" 

只有創建新的數組當鍵不存在(無)。

+0

適合我:-)。比Julians append_to_hash更優雅,所以這是我的答案。 – Pascal 2010-03-31 13:02:29

+0

重置默認也將工作:http://stackoverflow.com/questions/3818623/marshal-ruby-hash-with-default-proc-remove-the-default-proc – Ashitaka 2014-03-22 17:18:06

1

您可能會誤解Hash.default的工作原理。

之前你Marshal.dump,打印數據結構。這是{}。這是因爲您將每個字符串連接到nil,而不是一個空數組。下面的代碼說明並解決了您的問題。

s = Hash.new 
s.default = Array.new 
s[0] = [] 
s[0] << "Tigger" 
s[7] = [] 
s[7] << "Ruth" 
s[7] << "Puuh" 
p s 
data = Marshal.dump(s) 
ls = Marshal.restore(data) 
p ls 

返回:

{0=>["Tigger"], 7=>["Ruth", "Puuh"]} 
{0=>["Tigger"], 7=>["Ruth", "Puuh"]} 

編輯:

我插入了大量的數據到哈希

因此,也許一些輔助代碼將使插入流程更流暢:

def append_to_hash(hash, position, obj) 
    hash[position] = [] unless hash[position] 
    hash[position] << obj 
end 

s = Hash.new 
append_to_hash(s, 0, "Tigger") 
append_to_hash(s, 7, "Ruth") 
append_to_hash(s, 7, "Puuh") 
s.default = Array.new // this is only for reading 
p s 
data = Marshal.dump(s) 
ls = Marshal.restore(data) 
p ls 
+0

從我的例子打印數據轉儲給 「\ 004 \ B} \ 000 [\ B \」 \ vTigger \ 「\真相\」 \ tPuuh」 如此明顯的數據是存在的,但不能用 我試圖避免插入一個特殊的子句,因爲我將大量數據插入散列。 – Pascal 2010-03-31 11:37:43

+0

您可以使用'+'而不是'<<'方法追加元素,這樣您就不需要初始化每個新元素。 – 2010-03-31 11:41:09

+0

這裏不起作用 - 給出相同的結果。版本是jRuby 1.8.6的NetBeans。你能提供一個運行的例子嗎? – Pascal 2010-03-31 11:57:33

2

你可以只創建哈希結構,同時草簽Hash.new避免這樣的麻煩

h = Hash.new{ |a,b| a[b] = [] } 
h[:my_key] << "my value" 
+0

很好的答案,這比我的'append_to_hash'好得多。 – 2010-03-31 12:08:58

+0

不幸的是,它給了我一個「無法轉儲散列與默認過程」編組錯誤。我想這是因爲[]的重新定義。 – Pascal 2010-03-31 12:21:47

+0

你需要's.default = Array.new'或者你會得到那個錯誤。 – 2010-03-31 12:35:52

0

正如你不能用PROC一個散列使用Marshall.dump默認元素,你可以使用添加到每個陣列,而不是<<的稍微迂迴的方式:

s = Hash.new 
s.default = [] 
s[0] += [ "Tigger" ] 
s[7] += [ "Ruth" ] 
s[7] += [ "Pooh" ] 
data = Marshal.dump(s) 
ls = Marshal.restore(data) 
p ls