बराबर के बीच अंतर क्या है ?, eql ?, ===, और ==


552

मैं इन चार तरीकों के बीच के अंतर को समझने की कोशिश कर रहा हूं। मुझे पता है कि डिफ़ॉल्ट रूप से उस ==विधि को कॉल करता है, equal?जो तब वापस आती है जब दोनों ऑपरेंड वास्तव में एक ही वस्तु को संदर्भित करते हैं।

===डिफ़ॉल्ट रूप से भी कॉल करता है ==जो कॉल करता है equal?... ठीक है, इसलिए यदि इन तीनों तरीकों को ओवरराइड नहीं किया जाता है, तो मुझे लगता है ===, ==और equal?बिल्कुल वही काम करते हैं?

अब आता है eql?। यह (डिफ़ॉल्ट रूप से) क्या करता है? क्या यह ऑपरेटर के हैश / आईडी पर कॉल करता है?

रूबी में इतने समानता के संकेत क्यों हैं? क्या उन्हें शब्दार्थ में भिन्न माना जाता है?


मैं सिर्फ एक आईआरबी शुरू किया और निम्न परिणाम जो तुम्हारा के विपरीत था ... इन 3 के सभी सत्य हैं: "a" == "a", "a" === "a"और "a".eql? "a"। लेकिन यह गलत है: "a".equal? "a"(मेरा माणिक 1.9.2-p180 है)
पीटरवुड

7
@Peter: ऐसा इसलिए है क्योंकि तार सभी समानता ऑपरेटरों को ओवरराइड करते हैं। का उपयोग कर की कोशिश कर रहा a = Object.new; b = Object.newहै तो सभी ==, ===, .equal?, .eql?वापस आ जाएगी trueके लिए aबनाम aऔर के लिए झूठी aबनाम b
निमो 157

जवाबों:


785

मैं यहां ऑब्जेक्ट डॉक्यूमेंटेशन का भारी उद्धरण देने जा रहा हूं , क्योंकि मुझे लगता है कि इसकी कुछ बेहतरीन व्याख्याएं हैं। मैं आपको इसे पढ़ने के लिए प्रोत्साहित करता हूं, और इन तरीकों के लिए दस्तावेज़ीकरण भी करता हूं, क्योंकि वे अन्य कक्षाओं में स्ट्रिंग की तरह ओवरराइड हैं ।

साइड नोट: यदि आप विभिन्न वस्तुओं पर अपने लिए इन्हें आज़माना चाहते हैं, तो कुछ इस तरह का उपयोग करें:

class Object
  def all_equals(o)
    ops = [:==, :===, :eql?, :equal?]
    Hash[ops.map(&:to_s).zip(ops.map {|s| send(s, o) })]
  end
end

"a".all_equals "a" # => {"=="=>true, "==="=>true, "eql?"=>true, "equal?"=>false}

== - सामान्य "समानता"

ऑब्जेक्ट स्तर पर, ==केवल तभी लौटाता है जब objऔर otherसमान ऑब्जेक्ट हो। आमतौर पर, इस पद्धति को वर्ग-विशिष्ट अर्थ प्रदान करने के लिए वंशज कक्षाओं में ओवरराइड किया जाता है।

यह सबसे आम तुलना है, और इस तरह सबसे मौलिक स्थान जहां आप (एक वर्ग के लेखक के रूप में) यह तय करते हैं कि दो वस्तुएं "बराबर" हैं या नहीं।

=== - मामला समानता

क्लास ऑब्जेक्ट के लिए, प्रभावी रूप से कॉलिंग के समान है #==, लेकिन आमतौर पर वंशजों द्वारा मामले के बयानों में सार्थक शब्दार्थ प्रदान करने के लिए ओवरराइड किया जाता है।

यह अविश्वसनीय रूप से उपयोगी है। दिलचस्प ===कार्यान्वयन वाले चीजों के उदाहरण :

  • रेंज
  • regex
  • प्रोक (रूबी 1.9 में)

तो आप इस तरह की चीजें कर सकते हैं:

case some_object
when /a regex/
  # The regex matches
when 2..4
  # some_object is in the range 2..4
when lambda {|x| some_crazy_custom_predicate }
  # the lambda returned true
end

कैसे स्वच्छ कोड + एक बहुत क्लीनर बना सकते हैं के एक स्वच्छ उदाहरण के लिए यहाँ मेरा जवाब देखें । और हां, अपना स्वयं का कार्यान्वयन प्रदान करके , आप कस्टम शब्दार्थ प्राप्त कर सकते हैं ।caseRegex===case

eql?- Hashसमानता

eql?यदि यह विधि सही है objऔर otherउसी हैश कुंजी को संदर्भित करता है। इसका उपयोग Hashसमानता के लिए सदस्यों का परीक्षण करने के लिए किया जाता है । वर्ग की वस्तुओं के लिए Object, eql?का पर्याय है ==उपवर्ग सामान्य रूप से इस परंपरा eql?को अपनी ओवरराइड ==पद्धति के अनुसार जारी रखते हैं , लेकिन इसके अपवाद भी हैं। Numericप्रकार, उदाहरण के लिए, प्रकार में रूपांतरण करें ==, लेकिन पार नहीं eql?, इसलिए:

1 == 1.0     #=> true
1.eql? 1.0   #=> false

तो आप अपने स्वयं के उपयोगों के लिए इसे ओवरराइड करने के लिए स्वतंत्र हैं, या आप ओवरराइड कर सकते हैं ==और उपयोग कर सकते हैं, alias :eql? :==इसलिए दोनों तरीके समान व्यवहार करते हैं।

equal? - पहचान तुलना

इसके विपरीत ==, equal?विधि को उपवर्गों द्वारा कभी भी ओवरराइड नहीं किया जाना चाहिए: इसका उपयोग ऑब्जेक्ट आइडेंटिफिकेशन (यानी, a.equal?(b)यदि if aके समान वस्तु है b) निर्धारित करने के लिए किया जाता है ।

यह प्रभावी रूप से सूचक तुलना है।


32
जैसा कि मैंने आपके उत्तर से समझा, सख्ती है: बराबर? <eql? <== <=== आम तौर पर, आप == का उपयोग करते हैं। कुछ ढीले उद्देश्यों के लिए, आप === का उपयोग करते हैं। सख्त स्थिति के लिए, आप eql का उपयोग करते हैं ?, और पूर्ण पहचान के लिए, आप बराबर का उपयोग करते हैं?
आरा

21
कड़ाई की धारणा को लागू नहीं किया गया है या यहां तक ​​कि प्रलेखन में भी सुझाव दिया गया है, यह सिर्फ इतना होता है कि Numericइसे सख्त तरीके से संभालता है ==। यह वास्तव में कक्षा के लेखक तक है। ===अक्सर caseबयानों के बाहर प्रयोग किया जाता है ।
jtbandes

4
== बड़े / छोटे के मामले में भी समानता है। यानी, यदि आप तुलनात्मक शामिल करते हैं, तो इसे <=> रिटर्निंग 0. के संदर्भ में परिभाषित किया जाएगा। यही कारण है कि 1 == 1.0 रिटर्न सही है।
एपिरोस

5
@ सावा मैं आमतौर पर ==="माचिस" (मोटे तौर पर) के रूप में सोचता हूं । जैसे कि, "रेगेक्सपी स्ट्रिंग से मेल खाता है" या "रेंज मैच (संख्या) शामिल करता है"।
केल्विन

7
मजेदार तथ्य: आधिकारिक डॉक्स अब इस उत्तर से लिंक करते हैं (देखें ruby-doc.org/core-2.1.5/… )।
मार्क अमेरी डे

46

मुझे jtbandes उत्तर पसंद है, लेकिन चूंकि यह बहुत लंबा है, इसलिए मैं अपना खुद का कॉम्पैक्ट उत्तर दूंगा:

==, ===, eql?,equal?
4 तुलनाकारक, यानी कर रहे हैं। रूबी में 2 वस्तुओं की तुलना करने के 4 तरीके।
जैसा कि, रूबी में, सभी तुलनित्र (और अधिकांश ऑपरेटर) वास्तव में विधि-कॉल हैं, आप इन तुलनात्मक तरीकों के शब्दार्थ को स्वयं बदल सकते हैं, परिभाषित कर सकते हैं। हालांकि, यह समझना महत्वपूर्ण है, जब रूबी की आंतरिक भाषा किस तुलनित्र का उपयोग करती है:

==(मान तुलना)
रूबी का उपयोग करता है: == हर जगह 2 वस्तुओं के मूल्यों की तुलना करने के लिए , जैसे। हैश मान:

{a: 'z'}  ==  {a: 'Z'}    # => false
{a: 1}    ==  {a: 1.0}    # => true

===(केस तुलना)
रूबी उपयोग करता है: === मामले में / जब निर्माण करता है। निम्नलिखित कोड स्निपेट तार्किक रूप से समान हैं:

case foo
  when bar;  p 'do something'
end

if bar === foo
  p 'do something'
end

eql?(हैश-की तुलना)
रूबी उपयोग करता है: eql? (हैश की तुलना करने के लिए विधि हैश के साथ संयोजन में)। ज्यादातर कक्षाओं में: eql? के साथ समान है: ==।
ज्ञान के बारे में: eql? केवल महत्वपूर्ण है, जब आप अपनी विशेष कक्षाएं बनाना चाहते हैं:

class Equ
  attr_accessor :val
  alias_method  :initialize, :val=
  def hash()           self.val % 2             end
  def eql?(other)      self.hash == other.hash  end
end

h = {Equ.new(3) => 3,  Equ.new(8) => 8,  Equ.new(15) => 15}    #3 entries, but 2 are :eql?
h.size            # => 2
h[Equ.new(27)]    # => 15

नोट: आमतौर पर इस्तेमाल किया जाने वाला रूबी श्रेणी का सेट भी हैश-की-तुलना पर निर्भर करता है।

equal?(वस्तु पहचान तुलना)
रूबी उपयोग करता है: बराबर? यह जाँचने के लिए कि क्या दो वस्तुएँ समान हैं। इस विधि (वर्ग के मूल आधार) को अधिलेखित नहीं किया जाना चाहिए।

obj = obj2 = 'a'
obj.equal? obj2       # => true
obj.equal? obj.dup    # => false

30
यह एक अच्छा जवाब है, लेकिन यह लगभग लगभग jtbandes का है। :)
विषमता

2
@odigity, लंबे समय तक लगभग 70%। मैं उस 30% पर खर्च करने के लिए कई चीजों के बारे में सोच सकता था।
कैरी स्वेवेलैंड

मुझे लगता है कि इसका उदाहरण eql?बहुत भ्रामक है। eql?एक समानता तुलना कि है लगातार कैसे हैश गणना की जाती है, यानी साथ a.eql?(b)गारंटी देता है कि a.hash == b.hash। यह केवल हैश कोड की तुलना नहीं करता है ।
एंड्री टारनटोसव

क्या वास्तव में मामला तुलना के बराबर है bar === fooऔर नहीं foo === bar? मुझे उम्मीद है कि उत्तरार्द्ध सही है और यह महत्वपूर्ण है क्योंकि कंपाइलर बाएं हाथ की ओर कहता है: === `'
एलेक्सिस विल्के

जहां तक ​​मुझे पता है, यह है bar === foo: रूबी बाएं हाथ की तरफ केस वैल्यू और दाईं ओर केस चर का उपयोग करती है। यह NPEs (नल सूचक अपवाद) से बचने के साथ करना पड़ सकता है।
एंड्रियास रेयो नाइप

33

समानता ऑपरेटरों: == और! =

== ऑपरेटर, जिसे समानता या डबल बराबर के रूप में भी जाना जाता है, दोनों वस्तुओं के समान और झूठे होने पर सही वापस आ जाएंगे यदि वे नहीं हैं।

"koan" == "koan" # Output: => true

= = ऑपरेटर, जिसे असमानता के रूप में भी जाना जाता है, == के विपरीत है। यह सच है कि अगर दोनों वस्तुएं समान नहीं हैं और झूठे हैं तो वे समान होंगे।

"koan" != "discursive thought" # Output: => true

ध्यान दें कि एक अलग क्रम में समान तत्वों वाले दो सरणियाँ समान नहीं हैं, एक ही अक्षर के अपरकेस और लोअरकेस संस्करण समान नहीं हैं और इसी तरह।

विभिन्न प्रकारों (जैसे, पूर्णांक और फ्लोट) की संख्या की तुलना करते समय, यदि उनका संख्यात्मक मान समान है, तो == सही वापस आएगा।

2 == 2.0 # Output: => true

बराबरी का?

== ऑपरेटर के विपरीत जो परीक्षण करता है यदि दोनों ऑपरेंड समान हैं, तो समान विधि यह जांचती है कि क्या दोनों ऑपरेंड एक ही ऑब्जेक्ट को संदर्भित करते हैं। यह रूबी में समानता का सबसे सख्त रूप है।

उदाहरण: a = "ज़ेन" बी = "ज़ेन"

a.object_id  # Output: => 20139460
b.object_id  # Output :=> 19972120

a.equal? b  # Output: => false

ऊपर के उदाहरण में, हमारे पास समान मूल्य के साथ दो तार हैं। हालांकि, वे दो अलग-अलग ऑब्जेक्ट हैं, अलग-अलग ऑब्जेक्ट आईडी के साथ। इसलिए, बराबर? विधि झूठी आएगी।

चलिए फिर से कोशिश करते हैं, केवल इस बार b a का संदर्भ होगा। ध्यान दें कि ऑब्जेक्ट ID दोनों वेरिएबल्स के लिए समान है, क्योंकि वे एक ही ऑब्जेक्ट को इंगित करते हैं।

a = "zen"
b = a

a.object_id  # Output: => 18637360
b.object_id  # Output: => 18637360

a.equal? b  # Output: => true

eql?

हैश क्लास में, इकला? विधि यह समानता के लिए कुंजी का परीक्षण करने के लिए प्रयोग किया जाता है। इसे समझाने के लिए कुछ पृष्ठभूमि की आवश्यकता होती है। कंप्यूटिंग के सामान्य संदर्भ में, एक हैश फ़ंक्शन किसी भी आकार की एक स्ट्रिंग (या फ़ाइल) लेता है और निश्चित आकार का एक स्ट्रिंग या पूर्णांक बनाता है जिसे हैशकोड कहा जाता है, जिसे आमतौर पर केवल हैश के रूप में संदर्भित किया जाता है। कुछ आमतौर पर उपयोग किए जाने वाले हैशकोड प्रकार MD5, SHA-1 और CRC हैं। इनका उपयोग एन्क्रिप्शन एल्गोरिदम, डेटाबेस इंडेक्सिंग, फ़ाइल अखंडता जाँच आदि में किया जाता है। कुछ प्रोग्रामिंग भाषाएं, जैसे रूबी, एक संग्रह प्रकार प्रदान करती हैं जिसे हैश टेबल कहा जाता है। हैश टेबल डिक्शनरी जैसे संग्रह हैं जो जोड़े में डेटा संग्रहीत करते हैं, जिसमें अद्वितीय कुंजी और उनके संबंधित मूल्य शामिल हैं। हुड के तहत, उन कुंजियों को हैशकोड के रूप में संग्रहीत किया जाता है। हैश टेबल को आमतौर पर सिर्फ हैश के रूप में संदर्भित किया जाता है। ध्यान दें कि हैशकेन शब्द हैशकोड या हैश टेबल को कैसे संदर्भित करता है।

रूबी हैशकोड बनाने के लिए हैश नामक एक बिल्ट-इन विधि प्रदान करता है। नीचे दिए गए उदाहरण में, यह एक स्ट्रिंग लेता है और एक हैशकोड लौटाता है। ध्यान दें कि समान मान वाले स्ट्रिंग्स में हमेशा समान हैशकोड होते हैं, भले ही वे अलग-अलग ऑब्जेक्ट (अलग ऑब्जेक्ट आईडी के साथ) हों।

"meditation".hash  # Output: => 1396080688894079547
"meditation".hash  # Output: => 1396080688894079547
"meditation".hash  # Output: => 1396080688894079547

हैश विधि को कर्नेल मॉड्यूल में लागू किया गया है, जो ऑब्जेक्ट क्लास में शामिल है, जो सभी रूबी ऑब्जेक्ट्स का डिफ़ॉल्ट रूट है। कुछ वर्ग जैसे कि प्रतीक और पूर्णांक डिफ़ॉल्ट कार्यान्वयन का उपयोग करते हैं, अन्य लोग जैसे स्ट्रिंग और हैश अपने स्वयं के कार्यान्वयन प्रदान करते हैं।

Symbol.instance_method(:hash).owner  # Output: => Kernel
Integer.instance_method(:hash).owner # Output: => Kernel

String.instance_method(:hash).owner  # Output: => String
Hash.instance_method(:hash).owner  # Output: => Hash

रूबी में, जब हम किसी हैश (संग्रह) में कुछ संग्रहीत करते हैं, तो एक कुंजी (जैसे, स्ट्रिंग या प्रतीक) के रूप में प्रदान की गई वस्तु को हैशकोड के रूप में परिवर्तित और संग्रहीत किया जाता है। बाद में, हैश (संग्रह) से एक तत्व प्राप्त करते समय, हम एक कुंजी के रूप में एक वस्तु प्रदान करते हैं, जिसे हैशकोड में बदल दिया जाता है और मौजूदा कुंजी की तुलना में। यदि कोई मेल है, तो संबंधित आइटम का मान लौटाया जाता है। Eql का उपयोग करके तुलना की जाती है? हुड के तहत विधि।

"zen".eql? "zen"    # Output: => true
# is the same as
"zen".hash == "zen".hash # Output: => true

ज्यादातर मामलों में, eql? विधि == विधि के समान व्यवहार करती है। हालाँकि, कुछ अपवाद हैं। उदाहरण के लिए, eql? जब एक पूर्णांक की तुलना एक फ्लोट से करते हैं तो निहित प्रकार रूपांतरण नहीं करते हैं।

2 == 2.0    # Output: => true
2.eql? 2.0    # Output: => false
2.hash == 2.0.hash  # Output: => false

मामला समानता ऑपरेटर: ===

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

String === "zen"  # Output: => true
Range === (1..2)   # Output: => true
Array === [1,2,3]   # Output: => true
Integer === 2   # Output: => true

वही परिणाम अन्य तरीकों से प्राप्त किया जा सकता है जो संभवतः नौकरी के लिए सबसे उपयुक्त हैं। आमतौर पर कोड लिखना बेहतर होता है जो दक्षता और संक्षिप्तता का त्याग किए बिना जितना संभव हो उतना स्पष्ट होकर पढ़ना आसान है।

2.is_a? Integer   # Output: => true
2.kind_of? Integer  # Output: => true
2.instance_of? Integer # Output: => false

ध्यान दें कि अंतिम उदाहरण गलत है, क्योंकि पूर्णांक 2 फिक्सनम वर्ग के उदाहरण हैं, जो इंटेक्स वर्ग का एक उपवर्ग है। ===, is_a? और inst_of? यदि ऑब्जेक्ट दिए गए वर्ग या किसी उपवर्ग का एक उदाहरण है, तो तरीके सही हैं। Inst_of पद्धति कठोर है और केवल तभी सही है जब ऑब्जेक्ट उस सटीक वर्ग का उदाहरण है, न कि उपवर्ग।

Is_a और kind_of? तरीकों को कर्नेल मॉड्यूल में लागू किया जाता है, जिसे ऑब्जेक्ट क्लास द्वारा मिलाया जाता है। दोनों एक ही विधि के लिए उपनाम हैं। आइए सत्यापित करें:

कर्नेल.instance_method (: kind_of?) == कर्नेल.instance_method ((is_a?) # आउटपुट: => सत्य

श्रेणी = = का कार्यान्वयन

जब === ऑपरेटर को रेंज ऑब्जेक्ट पर बुलाया जाता है, तो यह सही होता है यदि दाईं ओर का मूल्य बाईं ओर की सीमा के भीतर आता है।

(1..4) === 3  # Output: => true
(1..4) === 2.345 # Output: => true
(1..4) === 6  # Output: => false

("a".."d") === "c" # Output: => true
("a".."d") === "e" # Output: => false

याद रखें कि === ऑपरेटर बाएं हाथ की वस्तु का === तरीका बताता है। तो (१.४) === ३ (१.४) के बराबर है। === ३. दूसरे शब्दों में, बाएं हाथ के संचालन का वर्ग परिभाषित करेगा कि === विधि का कार्यान्वयन कौन सा होगा कहा जाता है, तो ऑपरेंड की स्थिति विनिमेय नहीं है।

Regexp का कार्यान्वयन ===

सही पर लौटाता है यदि दाईं ओर का तार बाईं ओर नियमित अभिव्यक्ति से मेल खाता है। / zen / === "प्रैक्टिस ज़ज़ेन टुडे" # आउटपुट: => सच # "प्रैक्टिस ज़ज़ेन टुडे" = ~ / zen / जैसा ही है

केस / जब बयानों पर === ऑपरेटर का निहित उपयोग

इस ऑपरेटर का उपयोग हुड के तहत केस / जब बयानों के लिए भी किया जाता है। यह इसका सबसे आम उपयोग है।

minutes = 15

case minutes
  when 10..20
    puts "match"
  else
    puts "no match"
end

# Output: match

ऊपर के उदाहरण में, अगर रूबी ने दोहरे समान ऑपरेटर (==) का उपयोग किया था, तो 10..20 की सीमा को पूर्णांक के बराबर नहीं माना जाएगा जैसे कि 15. वे मेल खाते हैं क्योंकि ट्रिपल बराबर ऑपरेटर (===) है निहितार्थ सभी मामलों में / जब बयान। उपरोक्त उदाहरण में कोड इसके बराबर है:

if (10..20) === minutes
  puts "match"
else
  puts "no match"
end

पैटर्न मिलान ऑपरेटरों: = ~ और ~!

= ~ (बराबर-टिल्ड) और! ~ (बैंग-टिल्ड) ऑपरेटरों का उपयोग रेगेक्स पैटर्न के खिलाफ तार और प्रतीकों से मेल खाने के लिए किया जाता है।

स्ट्रिंग और प्रतीक वर्गों में = ~ विधि का कार्यान्वयन एक तर्क के रूप में एक नियमित अभिव्यक्ति (रेगेक्स क्लास का एक उदाहरण) की अपेक्षा करता है।

"practice zazen" =~ /zen/   # Output: => 11
"practice zazen" =~ /discursive thought/ # Output: => nil

:zazen =~ /zen/    # Output: => 2
:zazen =~ /discursive thought/  # Output: => nil

रेगेक्स क्लास में कार्यान्वयन एक तर्क के रूप में एक स्ट्रिंग या प्रतीक की अपेक्षा करता है।

/zen/ =~ "practice zazen"  # Output: => 11
/zen/ =~ "discursive thought" # Output: => nil

सभी कार्यान्वयनों में, जब स्ट्रिंग या प्रतीक Regexp पैटर्न से मेल खाता है, तो यह एक पूर्णांक देता है जो कि मैच की स्थिति (सूचकांक) है। यदि कोई मेल नहीं है, तो यह शून्य देता है। याद रखें कि, रूबी में, कोई भी पूर्णांक मान "सत्य" है और शून्य "मिथ्या" है, इसलिए = ~ ऑपरेटर का उपयोग यदि कथन और टर्नरी ऑपरेटरों में किया जा सकता है।

puts "yes" if "zazen" =~ /zen/ # Output: => yes
"zazen" =~ /zen/?"yes":"no" # Output: => yes

यदि स्टेटमेंट्स छोटे हों तो लिखने के लिए पैटर्न-मैचिंग ऑपरेटर भी उपयोगी होते हैं। उदाहरण:

if meditation_type == "zazen" || meditation_type == "shikantaza" || meditation_type == "kinhin"
  true
end
Can be rewritten as:
if meditation_type =~ /^(zazen|shikantaza|kinhin)$/
  true
end

~ ~ ऑपरेटर = ~ के विपरीत है, यह सच है जब कोई मैच नहीं होता है और एक मैच होने पर झूठा होता है।

अधिक जानकारी इस ब्लॉग पोस्ट पर उपलब्ध है ।


6
मुझे यह वर्तमान में स्वीकार किए गए उत्तर की तुलना में बेहतर उत्तर लगता है, क्योंकि यह अच्छे उदाहरण प्रदान करता है और इस बारे में कम अस्पष्ट है कि विभिन्न प्रकार की समानता का क्या अर्थ है और वे क्यों मौजूद हैं / जहां उनका उपयोग किया जाता है।
Qqwy

1
बहुत विस्तृत उत्तर, लेकिन मेरी irb पर (रूबी v। 2.2.1) :zen === "zen"झूठी
माइक आर

@MikeR मुझे बताने के लिए धन्यवाद। मैंने जवाब सही दिया है।
BrunoFacca

मुझे लगता है कि आपका मतलब type_of है? "अंतिम उदाहरण को गलत मानें क्योंकि 2 जैसे पूर्णांक फ़िक्नम वर्ग के उदाहरण हैं, जो इंटेगर वर्ग का एक उपवर्ग है। ===, is_a? और inst_of? (TYPE_OF?)"
user1883793

1
मुझे यह जवाब पसंद है। धन्यवाद
अब्दुल्ला Fadhel

9

समानता से निपटने के लिए रूबी कई अलग-अलग तरीकों को उजागर करती है:

a.equal?(b) # object identity - a and b refer to the same object

a.eql?(b) # object equivalence - a and b have the same value

a == b # object equivalence - a and b have the same value with type conversion.

नीचे दिए गए लिंक पर क्लिक करके पढ़ना जारी रखें, इससे मुझे स्पष्ट रूप से समझ में आ गई।

https://www.relishapp.com/rspec/rspec-expectations/v/2-0/docs/matchers/equality-matchers

आशा है कि यह दूसरों की मदद करता है।


8

=== # --- मामला समानता

== # --- सामान्य समानता

दोनों समान काम करते हैं लेकिन "===" यहां तक ​​कि केस स्टेटमेंट भी करते हैं

"test" == "test"  #=> true
"test" === "test" #=> true

यहाँ अंतर है

String === "test"   #=> true
String == "test"  #=> false

3
वे समान रूप से काम नहीं करते हैं, भले ही यह सच है कि जब a==bतब a===b। लेकिन a===bबहुत अधिक शक्तिशाली है। ===सममित नहीं है, और a===bइसका मतलब बहुत अलग है b===a, अकेले चलो a==b
mwfearnley

8

मैं ===ऑपरेटर पर विस्तार करना चाहूंगा ।

=== एक समानता ऑपरेटर नहीं है!

नहीं।

चलो उस बिंदु को वास्तव में पार करते हैं।

आप ===जावास्क्रिप्ट और PHP में एक समानता ऑपरेटर के रूप में परिचित हो सकते हैं , लेकिन यह सिर्फ रूबी में समानता ऑपरेटर नहीं है और मौलिक रूप से अलग शब्दार्थ है।

तो क्या करता ===है?

=== पैटर्न मिलान ऑपरेटर है!

  • === नियमित अभिव्यक्ति से मेल खाता है
  • === चेक में सदस्यता की सीमा होती है
  • === एक वर्ग की जाँच उदाहरण
  • === लैम्ब्डा एक्सप्रेशन कहता है
  • === कभी-कभी समानता की जांच करता है, लेकिन ज्यादातर यह नहीं करता है

तो यह पागलपन कैसे समझ में आता है?

  • Enumerable#grep===आंतरिक रूप से उपयोग करता है
  • case whenबयान ===आंतरिक रूप से उपयोग करते हैं
  • मजेदार तथ्य, आंतरिक रूप से rescueउपयोग करता है===

यही कारण है कि आप एक case whenबयान में नियमित अभिव्यक्ति और वर्गों और श्रेणियों और यहां तक ​​कि लैम्ब्डा अभिव्यक्तियों का उपयोग कर सकते हैं ।

कुछ उदाहरण

case value
when /regexp/
  # value matches this regexp
when 4..10
  # value is in range
when MyClass
  # value is an instance of class
when ->(value) { ... }
  # lambda expression returns true
when a, b, c, d
  # value matches one of a through d with `===`
when *array
  # value matches an element in array with `===`
when x
  # values is equal to x unless x is one of the above
end

ये सभी उदाहरण काम के साथ pattern === value-साथ grepविधि के साथ भी काम करते हैं ।

arr = ['the', 'quick', 'brown', 'fox', 1, 1, 2, 3, 5, 8, 13]
arr.grep(/[qx]/)                                                                                                                            
# => ["quick", "fox"]
arr.grep(4..10)
# => [5, 8]
arr.grep(String)
# => ["the", "quick", "brown", "fox"]
arr.grep(1)
# => [1, 1]

-8

मैंने उपरोक्त सभी के लिए एक सरल परीक्षण लिखा था।

def eq(a, b)
  puts "#{[a, '==',  b]} : #{a == b}"
  puts "#{[a, '===', b]} : #{a === b}"
  puts "#{[a, '.eql?', b]} : #{a.eql?(b)}"
  puts "#{[a, '.equal?', b]} : #{a.equal?(b)}"
end

eq("all", "all")
eq(:all, :all)
eq(Object.new, Object.new)
eq(3, 3)
eq(1, 1.0)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.