रूबी में यह बताने का एक सुंदर तरीका है कि क्या एक चर एक हैश या एक ऐरे है?


140

यह जाँचने के लिए कि @some_varमैं क्या कर रहा हूँ

if @some_var.class.to_s == 'Hash' 

मुझे यकीन है कि @some_varएक Hashया एक है अगर जाँच करने के लिए एक और अधिक सुंदर तरीका है Array


1
एंड्रयू: मैं एक एपीआई कॉल कर रहा हूं और JSON में मुझे वापस मिल जाता है, अगर कई परिणाम हैं मुझे एक ऐरे मिलता है लेकिन अगर एक ही है तो मुझे एक तत्व एरे के बजाय एक हैश मिलता है। क्या ऐरे बनाम हैश चेक करने से बेहतर आगे है?
ड्रिल

2
तो आप [result_hash, another_result_hash]या तो मिलता है या single_result_hash? जिसने भी एपीआई बनाया है वह अच्छा काम नहीं कर रहा है!
एंड्रयू ग्रिम

2
आप सही हैं, एंड्रयू, और मुझे यकीन है कि यह उन लोगों को प्राप्त करना बहुत आसान है जिन्होंने एपीआई को एक हैश बनाम सरणी के लिए परीक्षण करने के बजाय इसे ठीक करने के लिए लिखा है।
ओलिवियर 'एल्बाउम' शॉलर

मेरे पास @dripper जैसी ही स्थिति है। मेरे मामले में 3rd पार्टी HTTParty है जो XML फ़ाइल को पार्स करने के बाद यह तय करने का कोई तरीका नहीं है कि ऐसी स्थिति को संभालने का सबसे अच्छा तरीका क्या है जहां एक तत्व में 1-n बच्चे हो सकते हैं।
गंदे हेनरी

आपको अड्डी ग्रिम्स स्क्रैंकास्ट देखना चाहिए: rubytapas.com/2016/10/17/episode-451-advanced-class-membership और शायद कैबोस को स्वीकार किए गए उत्तर दें।
अलेक्जेंडर प्रेबर

जवाबों:


261

आप बस कर सकते हैं:

@some_var.class == Hash

या भी कुछ इस तरह:

@some_var.is_a?(Hash)

यह ध्यान देने योग्य है कि "is_a?" विधि सत्य है यदि वर्ग कहीं भी पूर्वजों के पेड़ में है। उदाहरण के लिए:

@some_var.is_a?(Object)  # => true

उपरोक्त सही है यदि @some_var एक हैश या अन्य वर्ग का उदाहरण है जो ऑब्जेक्ट से उपजा है। इसलिए, यदि आप == या inst_of का उपयोग करके वर्ग प्रकार पर एक सख्त मिलान चाहते हैं? विधि शायद वही है जो आप खोज रहे हैं।


20
is_a?सबसे अच्छा विकल्प है, क्योंकि यह trueउपवर्गों के लिए भी लौटता है।
फैबियो बतिस्ता

और, ज़ाहिर है, आप कोष्ठक भी छोड़ देते हैं, इसलिए @som_var.is_a? Hashभी काम करता है :)
गस शॉर्ट्ज़

7
सावधान रहें, यह वास्तव में आपको खराब कर सकता है यदि कोई व्यक्ति आपको ActiveSupport :: HashWithIndiffernAccess का एक उदाहरण दे रहा है। जो हैश की तरह प्रतिक्रिया करता है, लेकिन वास्तव में हैश नहीं है। :(
अनफ्लोरेस

मुझे डक-टाइपिंग के बारे में विस्तार से जाने वाले उत्तर भी पसंद आए हैं, क्योंकि मूल लेखक स्पष्ट रूप से एक प्रकार की जांच करने के लिए माणिक तरीके की तलाश में था।
नोबोडिस नाइटमेयर

3
@ हनफ्लोर हश से ActiveSupport::HashWithIndifferentAccessविरासत में मिला है, इसलिए @some_var.is_a?(Hash)इस मामले में भी सही लौटेगा। (मैं सिर्फ एक ही सवाल था और HashWithIndifferentAccess मामला और आपकी टिप्पणी से थोड़ा भ्रमित हो गया ... इसलिए मैं स्पष्ट करना चाहता था)
Stilzk1n

38

सबसे पहले, शाब्दिक प्रश्न का सबसे अच्छा उत्तर है

Hash === @some_var

लेकिन वास्तव में इस सवाल का जवाब यह दिखाना चाहिए कि कैसे यहां डक-टाइपिंग की जाती है। यह इस बात पर निर्भर करता है कि आपको किस प्रकार के बतख की आवश्यकता है।

@some_var.respond_to?(:each_pair)

या

@some_var.respond_to?(:has_key?)

या और भी

@some_var.respond_to?(:to_hash)

आवेदन के आधार पर सही हो सकता है।


25

आमतौर पर माणिक में जब आप "टाइप" की तलाश में होते हैं तो आप वास्तव में "डक-टाइप" चाहते हैं या "डक की तरह क्वैक होता है?"। आप देखेंगे कि क्या यह एक निश्चित विधि का जवाब देता है:

@some_var.respond_to?(:each)

आप @some_var पर iterate कर सकते हैं क्योंकि यह प्रतिसाद देता है: प्रत्येक

यदि आप वास्तव में प्रकार जानना चाहते हैं और यदि यह हैश या एरे है तो आप कर सकते हैं:

["Hash", "Array"].include?(@some_var.class)  #=> check both through instance class
@some_var.kind_of?(Hash)    #=> to check each at once
@some_var.is_a?(Array)   #=> same as kind_of

यदि आपका कोड डेटा के क्रम पर निर्भर है (जैसे कि आप प्रत्येक_विथ_index का उपयोग कर रहे हैं) तो यह काम नहीं करेगा। तत्वों का क्रम अलग तरह से हैश और सरणियों के बीच लागू किया जाता है और यह रूबी संस्करणों के बीच अलग होता है। ( intertwingly.net/slides/2008/oscon/ruby19/22 )
juan2raid

1
@ juan2raid: यदि आदेश महत्वपूर्ण है, तो sortपहले उस पर कॉल करें ।
एंड्रयू ग्रिम

@ दूसरा उदाहरण स्ट्रिंग को वर्ग में बदलना चाहिए। <br/>["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
OBCENEIKON

12
Hash === @some_var #=> return Boolean

इसे केस स्टेटमेंट के साथ भी इस्तेमाल किया जा सकता है

case @some_var
when Hash
   ...
when Array
   ...
end

4

मैं इसका उपयोग करता हूं:

@var.respond_to?(:keys)

यह Hash और ActiveSupport :: HashWithIndifferentAccess के लिए काम करता है।


4

व्यवहार में, आप अक्सर इस पर निर्भर करते हुए अलग तरह से कार्य करना चाहेंगे कि एक चर एक ऐरे या हैश है, न कि केवल बताएं। इस स्थिति में, एक सुंदर मुहावरा निम्नलिखित है:

case item
  when Array
   #do something
  when Hash
   #do something else
end

ध्यान दें कि आप .classविधि को कॉल नहीं करते हैं item


2

आप उपयोग कर सकते हैं instance_of?

जैसे

@some_var.instance_of?(Hash)

ध्यान दें कि यह उपवर्गों के लिए काम नहीं करता है ! उदाहरण के लिए, यदि आपके पास एक ActiveRecord::Collectionऔर कोशिश है instance_of?(Array)तो यह वापस आ जाएगी false, जबकि is_a?(Array)वापस आ जाएगी true
टॉम लॉर्ड

0

यदि आप परीक्षण करना चाहते हैं कि कोई वस्तु कड़ाई से है या फैली हुई है Hash, तो उपयोग करें:

value = {}
value.is_a?(Hash) || value.is_a?(Array) #=> true

लेकिन रूबी के बत्तख टाइपिंग का मूल्य बनाने के लिए, आप कुछ ऐसा कर सकते हैं:

value = {}
value.respond_to?(:[]) #=> true

यह उपयोगी है जब आप केवल value[:key]सिंटैक्स का उपयोग करके कुछ मूल्य तक पहुंचना चाहते हैं ।

कृपया ध्यान दें कि Array.new["key"]एक उठाएंगे TypeError


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.