दिलचस्प पोस्ट
एक विशिष्ट संपत्ति की संपत्ति जानकारी कैसे प्राप्त करें? मेवेन 2 के साथ एक रननबल जार का निर्माण जावा के साथ "हैलो वर्ल्ड" स्ट्रिंग के प्रत्येक व्यक्तिगत शब्द को रिवर्स करें एक सर्कल स्विच में एक UIImage कट (आईओएस) वार्जेंट 'डिफ़ॉल्ट' मशीन नाम कैसे बदल सकता है? डेटाट्रिगर जहां मूल्य शून्य नहीं है? कोष्ठक में नहीं केवल अल्पविराम मैच के लिए Regex? Microsoft.Jet.OleDb और Microsoft.Ace.OleDb के बीच का अंतर FFmpeg के साथ वीडियो घूम रहा है एएसपी.नेट एमवीसी: डेटाएनेटेशन द्वारा कस्टम वैल्यूशन Google मानचित्र API v3 – सेट सीमा और केंद्र शास्त्रीय एएसपी में संग्रहित प्रक्रिया का उपयोग करना। निष्पादित करें और परिणाम प्राप्त करें SQL "IN" स्टेटमेंट के लिनक संस्करण जावा keystore में .cer प्रमाणपत्र कैसे आयात करें? विस्मयादिबोधक चिह्न समारोह से पहले क्या करता है?

बिना किसी नीले जांच के, नेस्टेड हैशों में लापता तत्वों के लिए NoMethodError से कैसे बचें?

मैं गहराई से नेस्टेड हैश में प्रत्येक स्तर पर nil लिए जाँच करने से बचने का एक अच्छा तरीका तलाश रहा हूं उदाहरण के लिए:

 name = params[:company][:owner][:name] if params[:company] && params[:company][:owner] && params[:company][:owner][:name] 

इसके लिए तीन चेक की आवश्यकता है, और बहुत बदसूरत कोड के लिए बनाता है। इस के आसपास पाने के लिए कोई रास्ता?

वेब के समाधान से एकत्रित समाधान "बिना किसी नीले जांच के, नेस्टेड हैशों में लापता तत्वों के लिए NoMethodError से कैसे बचें?"

रुबी 2.3.0 ने एक नई विधि की शुरुआत की है जिसे Hash और Array दोनों पर dig गया है जो इस समस्या को पूरी तरह से हल करता है।

 name = params.dig(:company, :owner, :name) 

यदि किसी भी स्तर पर कुंजी अनुपलब्ध है तो यह nil देता है

यदि आप रूबी के संस्करण 2.3 से अधिक पुराने का उपयोग कर रहे हैं, तो आप ruby_dig मणि का उपयोग कर सकते हैं या इसे स्वयं लागू कर सकते हैं:

 module RubyDig def dig(key, *rest) if value = (self[key] rescue nil) if rest.empty? value elsif value.respond_to?(:dig) value.dig(*rest) end end end end if RUBY_VERSION < '2.3' Array.send(:include, RubyDig) Hash.send(:include, RubyDig) end 

कार्यक्षमता और स्पष्टता के बीच सबसे अच्छा समझौता आईएमओ रॅगनवाल्ड और एंड्रॉइड है। इसके साथ, आप ऐसा करेंगे:

 params[:company].andand[:owner].andand[:name] 

यह try करने के समान है, लेकिन इस मामले में बहुत बेहतर पढ़ता है क्योंकि आप अभी भी सामान्य संदेश भेज रहे हैं, लेकिन इस बीच एक सीमा के साथ उस कॉल को ध्यान में रखते हुए कि आप विशेष रूप से एनआईएल का इलाज कर रहे हैं

मुझे नहीं पता कि आप क्या चाहते हैं, लेकिन शायद आप यह कर सकते हैं?

 name = params[:company][:owner][:name] rescue nil 

दूसरे समाधान के बराबर है कि उपयोगकर्ता ने mpd सुझाव दिया, केवल और मुहावरेदार रूबी:

 class Hash def deep_fetch *path path.inject(self){|acc, e| acc[e] if acc} end end hash = {a: {b: {c: 3, d: 4}}} p hash.deep_fetch :a, :b, :c #=> 3 p hash.deep_fetch :a, :b #=> {:c=>3, :d=>4} p hash.deep_fetch :a, :b, :e #=> nil p hash.deep_fetch :a, :b, :e, :f #=> nil 

यदि यह रेल है, तो इसका उपयोग करें

 params.try(:[], :company).try(:[], :owner).try(:[], :name) 

ओह रुको, वह भी कुटिलता है 😉

यदि आप बंदरपैचिंग में जाना चाहते हैं तो आप ऐसा कुछ कर सकते हैं

 क्लास NilClass
   def [] (कुछ भी)
     शून्य
   समाप्त
 समाप्त

फिर एक params[:company][:owner][:name] लिए कॉल params[:company][:owner][:name] किसी भी बिंदु पर किसी भी बिंदु पर नीडिंत हैश शून्य है।

संपादित करें: यदि आप एक सुरक्षित मार्ग चाहते हैं जो स्वच्छ कोड भी प्रदान करता है तो आप ऐसा कुछ कर सकते हैं

 वर्ग हैश
   डेफ चेन (* आर्ग्स)
     एक्स = 0
     वर्तमान = स्व [आर्ग्स [x]]
     जबकि वर्तमान && x <args.size - 1
       x + = 1
       वर्तमान = चालू [आर्ग्स [x]]
     समाप्त
     वर्तमान
   समाप्त
 समाप्त

कोड ऐसा दिखेगा: params.chain(:company, :owner, :name)

आप रूबी हैश के लिए ऑटो-विविंगन जोड़ने के तरीकों में से एक को देखना चाह सकते हैं। निम्नलिखित स्टैक ओवरफ्लो धागे में वर्णित कई दृष्टिकोण हैं:

  • रूबी ऑटोवाविफिकेशन
  • रूबी हैश ऑटोवाविफिकेशन (पहलुओं)

मैं इसे इस रूप में लिखूंगा:

 name = params[:company] && params[:company][:owner] && params[:company][:owner][:name] 

यह जितना स्वच्छ नहीं है ? आईओ में ऑपरेटर , लेकिन रूबी में ऐसा नहीं है @ थिओ सिलीवीरा का जवाब भी अच्छा है, हालांकि यह धीमा होगा

क्या आप बहु-आयामी हैश का उपयोग करने से बचने में सक्षम हैं, और उपयोग करें

 params[[:company, :owner, :name]] 

या

 params[[:company, :owner, :name]] if params.has_key?([:company, :owner, :name]) 

बजाय?

एक बार कुरूपता लिखें, फिर इसे छिपाना

 def check_all_present(hash, keys) current_hash = hash keys.each do |key| return false unless current_hash[key] current_hash = current_hash[key] end true end 

(यद्यपि यह वास्तव में पुराना प्रश्न है, हालांकि यह जवाब मेरे जैसे कुछ स्टैकवॉवरफ्लो लोगों के लिए उपयोगी होगा, जो "बचाव शुरू" नियंत्रण संरचना अभिव्यक्ति के बारे में नहीं सोचता था।)

मैं एक कोशिश पकड़ बयान (रूबी भाषा में बचाव शुरू) के साथ ऐसा होता है:

 begin name = params[:company][:owner][:name] rescue #if it raises errors maybe: name = 'John Doe' end 

कर:

 params.fetch('company', {}).fetch('owner', {})['name'] 

इसके अलावा प्रत्येक चरण पर, यदि आप सरणी, स्ट्रिंग, या संख्यात्मक होते हैं, तो आप nil से बचने के लिए NilClass में बनाए गए उपयुक्त विधि का उपयोग कर सकते हैं। बस इस सूची की सूची में to_hash जोड़ें और उसका उपयोग करें।

 class NilClass; def to_hash; {} end end params['company'].to_hash['owner'].to_hash['name'] 

आपको मूल हैश परिभाषा तक पहुंच की आवश्यकता नहीं है – आप इसे h.instance_eval का उपयोग करने के बाद उड़ान पर [] विधि को ओवरराइड कर सकते हैं, उदा।

 h = {1 => 'one'} h.instance_eval %q{ alias :brackets :[] def [] key if self.has_key? key return self.brackets(key) else h = Hash.new h.default = {} return h end end } 

लेकिन यह आपके पास उस कोड के साथ आपकी मदद नहीं कर रहा है, क्योंकि आप किसी गलत मान पर भरोसा कर रहे हैं (उदाहरण के लिए, शून्य) और यदि आप "सामान्य" ऑटो-वाइविफिकेशन सामान से ऊपर की ओर से जुड़ा कोई भी काम करते हैं 'अन्तराल मूल्यों के लिए एक खाली हैश के साथ समाप्त करने जा रहे हैं, जो "सच" के रूप में मूल्यांकन करता है।

आप ऐसा कुछ कर सकते हैं – यह केवल निर्धारित मानों की जांच करता है और उन्हें रिटर्न देता है। आप उन्हें इस तरह से सेट नहीं कर सकते, क्योंकि हमें यह जानने का कोई तरीका नहीं है कि कॉल असाइनमेंट के एलएचएस पर है।

 module AVHash def deep(*args) first = args.shift if args.size == 0 return self[first] else if self.has_key? first and self[first].is_a? Hash self[first].send(:extend, AVHash) return self[first].deep(*args) else return nil end end end end h = {1=>2, 3=>{4=>5, 6=>{7=>8}}} h.send(:extend, AVHash) h.deep(0) #=> nil h.deep(1) #=> 2 h.deep(3) #=> {4=>5, 6=>{7=>8}} h.deep(3,4) #=> 5 h.deep(3,10) #=> nil h.deep(3,6,7) #=> 8 

फिर भी, हालांकि, आप केवल इसके साथ मूल्यों को जांच सकते हैं – उन्हें असाइन नहीं करें तो यह वास्तविक ऑटो-विवियन नहीं है क्योंकि हम सभी जानते हैं और इसे पर्ल में पसंद करते हैं।

 require 'xkeys' # on rubygems.org params.extend XKeys::Hash # No problem that we got params from somebody else! name = params[:company, :owner, :name] # or maybe... name = params[:company, :owner, :name, :else => 'Unknown'] # Note: never any side effects for looking # But you can assign too... params[:company, :reviewed] = true 

खतरनाक लेकिन काम करता है:

 class Object def h_try(key) self[key] if self.respond_to?('[]') end end 

हम नए कर सकते हैं

  user = { :first_name => 'My First Name', :last_name => 'my Last Name', :details => { :age => 3, :birthday => 'June 1, 2017' } } user.h_try(:first_name) # 'My First Name' user.h_try(:something) # nil user.h_try(:details).h_try(:age) # 3 user.h_try(:details).h_try(:nothing).h_try(:doesnt_exist) #nil 

"एच_ट्री" श्रृंखला "ट्राई" चेन के समान शैली का पालन करती है।

रुबी 2.3.0 के अनुसार:

आप उपयोग कर सकते हैं &. "सुरक्षित नेविगेशन ऑपरेटर" कहा जाता है: params&.[](:company)&.[](:owner)&.[](:name) यह एक पूरी तरह सुरक्षित है

यदि params शून्य है, तो params.dig(:company, :owner, :name) का उपयोग सुरक्षित रूप से params.dig(:company, :owner, :name) होगा।

हालांकि आप दोनों को इस प्रकार जोड़ सकते हैं: params&.dig(:company, :owner, :name)

इसलिए निम्न में से कोई भी उपयोग करने के लिए सुरक्षित है:

params&.[](:company)&.[](:owner)&.[](:name)

params&.dig(:company, :owner, :name)