यह एक और तरीका है कि कम डेटा की आवश्यकता है हैश बनाने के लिए।
A = B
A = B = C
और लाइनों के आदेश है महत्वहीन: अगर, उदाहरण के लिए, लाइन
A = B = C = D
मौजूद है, वहाँ निम्नलिखित में से किसी के लिए कोई जरूरत नहीं है।
कोड
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"]
नोटिस String#lines, split(/'\n'/)
के विपरीत, न्यूलाइन वर्ण रखता है। इस बिंदु पर उन्हें रखना जानबूझकर था; वे एक महत्वपूर्ण उद्देश्य की सेवा करते हैं, जैसा कि नीचे दिखाया जाएगा।
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
अब invokes 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", {}]
जो विघटित या है "disambiguated" में दो तत्व है और ब्लॉक चर करने के लिए आवंटित:
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[-1] == "\n" #=> true
में में w
परिणाम न्यू लाइन चरित्र की उपस्थिति हमें बता यह है लाइन में आखिरी शब्द, इसलिए हमें न्यूलाइन चरित्र को बंद करने और nil
:
g[w.chomp] = nil
#=> g["C"] = nil
पर मान सेट करने की आवश्यकता है
में जिसके परिणामस्वरूप:
h #=> {"A"=>{"B"=>{"C"=>nil}}}
स्ट्रिंग में न्यू लाइन चरित्र छोड़कर दूसरों की तुलना में अलग तरह से प्रत्येक पंक्ति पर अंतिम शब्द प्रसंस्करण के लिए आवश्यक "झंडा" प्रदान की है।
अन्य लाइनों को समान रूप से संसाधित किया जाता है।
उत्तर के लिए धन्यवाद। मैं बदले में नल पाने की कोशिश करूंगा। –
पत्तियों को कम करने के लिए अद्यतन देखें। – mudasobwa
धन्यवाद @ mudasobwa –