這是一個需要較少的數據的另一種方式構建哈希。如果,例如,線
A = B = C = D
存在時,就沒有必要爲以下任一操作:
A = B
A = B = C
和行的順序是不重要的。
代碼
def hashify(str)
str.lines.each_with_object({}) { |line, h|
line.split(/\s*=\s*/).reduce(h) { |g,w|
(w[-1] == "\n") ? g[w.chomp] = nil : g[w] ||= {} } }
end
例
str =<<_
A = B = C
G = I
A = B = D
A = E = F
G = H
A = K
G = J
_
hashify(str)
#=> {"A"=>{"B"=>{"C"=>nil, "D"=>nil}, "E"=>{"F"=>nil}, "K"=>nil},
# "G"=>{"I"=>nil, "H"=>nil, "J"=>nil}}
說明
對於str
以上:
a = str.lines
#=> ["A = B = C\n", "A = B = D\n", "A = E = F\n",
# "G = H\n", "G = I\n", "G = J\n"]
請注意,與split(/'\n'/)
不同,String#lines保留換行符。保持這一點是有意的;它們有一個重要的目的,如下所示。
enum = a.each_with_object({})
#=> #<Enumerator: ["A = B = C\n", "A = B = D\n", "A = E = F\n", "G = H\n",
# "G = I\n", "G = J\n"]:each_with_object({})>
我們可以枚舉轉換爲數組看到Array#each將傳遞到塊中的元素:
enum.to_a
#=> [["A = B = C\n", {}], ["A = B = D\n", {}], ["A = E = F\n", {}],
# ["G = H\n", {}], ["G = I\n", {}], ["G = J\n", {}]]
enum
現在調用each
給每個元件通入塊:
enum.each { |line, h| line.split(/\s*=\s*/).reduce(h) { |g,w|
(w[-1] == '\n') ? g[w.chomp] = nil : g[w] ||= {} } }
#=> {"A"=>{"B"=>{"C\n"=>{}, "D\n"=>{}}, "E"=>{"F\n"=>{}}},
# "G"=>{"H\n"=>{}, "I\n"=>{}, "J\n"=>{}}}
Array#each
傳入該塊的第一個值是:
["A = B = C\n", {}]
其被分解或「消歧」到它的兩個元件和分配給該塊的變量:
b = line.split(/\s*=\s*/)
#=> ["A", "B", "C\n"]
b.reduce(h) { |g,w|
(w[-1] == '\n') ? g[w.chomp] = nil : g[w] ||= {} }
#=> {}
初始值:
line = "A = B = C\n"
h = {}
我們現在在塊執行代碼對於reduce
是我們正在構建的散列h
,它最初是空的。當h
和"A"
被傳遞到塊,
g = h #=> {}
w = "A"
左右(提的是,需要爲"\n"
雙引號)
w[-1] == "\n"
#=> "A" == '\n'
#=> false
所以我們執行
g[w] ||= {}
#=> g['A'] ||= {}
#=> g['A'] = g['A'] || {}
#=> g['A'] = nil || {}
#=> {}
所以現在
h #=> {"A"=>{}}
g[w] => {}
然後被傳遞迴回reduce
和用於傳遞到塊中的第二元件的塊的變量是:
g = g["A"] #=> {}
w = "B"
由於
w[-1] == "\n" #=> false
我們再次執行
g[w] ||= {}
#=> g["B"] ||=> {} => {}
和現在
h #=> {"A"=>{"B"=>{}}}
最後,[g["B"], "C\n"]
傳遞到塊,分解,分配給塊變量:
g = g["B"] #=> {}
w = "C\n"
但換行符的存在w
結果
w[-1] == "\n" #=> true
告訴我們它是因此我們需要去掉換行符並將其值設置爲nil
:
g[w.chomp] = nil
#=> g["C"] = nil
導致:
h #=> {"A"=>{"B"=>{"C"=>nil}}}
字符串中離開換行符處理每行的最後一個字不同於其他人提供所需的「標誌」。
其他行的處理方式相似。
感謝您的回答。我會嘗試取而代之。 – 2014-11-21 14:11:59
查看如何取消樹葉的更新。 – mudasobwa 2014-11-21 14:36:06
謝謝@mudasobwa – 2014-11-21 14:44:17