Eql?, === və == arasındakı fərq nədir?

Bu dörd üsul arasındakı fərqləri anlamağa çalışıram. Varsayım ki, == equal? üsul çağırır equal? hər iki əməli eyni obyektə aid olduğunda doğru olan qayıdır.

=== default olaraq da zənglər == , zənglər equal? ... tamam, buna görə də bütün bu üç üsulun əvəz edilməməsi halında, mən === , ==equal? olduğunu düşünürəm equal? Eyni şeyi edirsiniz?

İndi eql? gəlir eql? . Nədir (default olaraq)? Zəng bir operand hash / id təşkil edirmi?

Niyə Ruby çox bərabər əlamətləri var? Semantikada fərqli olmalıdırlar?

502
23 авг. 23 Avqustda denniss qoydu 2011-08-23 09:13 '11 at 9:13 2011-08-23 09:13
@ 7 cavab

Buradakı obyektlə əlaqədar sənədləri çoxdan sitat gətirəcəyəm, çünki düşünürəm ki, bəzi böyük şərhlər var. String kimi digər siniflərdə yenidən təyin edildikdən sonra, bu metodların sənədlərini, eləcə də onu oxumağınızı məsləhət görürəm.

Qeyd: Fərqli obyektlərdə özünüz üçün sınamaq istəyirsinizsə, belə bir şəkildə istifadə edin:

 class Object def all_equals(o) ops = [:==, :===, :eql?, :equal?] Hash[ops.map( {|s| send(s, o) })] end end "a".all_equals "a" # => {"=="=>true, "==="=>true, "eql?"=>true, "equal?"=>false} 

== - ümumi "bərabərlik"

Obje səviyyəsində, == yalnız objother eyni obyekt olduqda doğru olur. Tipik olaraq, bu metod, sinifə xüsusi bir dəyər təmin etmək üçün nəsil siniflərində yenidən təyin edilir.

Bu ən ümumi müqayisəsidir və buna görə də siz (sinif müəllifi kimi) iki obyektin "bərabərdir" və ya olmadığı barədə ən əsas yerdir.

=== - halda bərabərlik

Obyekt sinfi üçün, həqiqətən #== çağırışı ilə eyni olsa da, ifadələrində mənalı semantik təmin etmək üçün ümumiyyətlə nüsarlar tərəfindən köçürülür.

Bu inanılmaz dərəcədə faydalıdır. Maraqlı tətbiqləri olan əşyaların nümunələri === :

  • Range
  • Regex
  • Proc (Ruby 1.9'da)

Beləliklə, siz aşağıdakı kimi işlər edə bilərsiniz:

 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 

case + Regex kodunu daha təmiz hala gətirmək üçün səliqəli bir nümunə üçün buraya cavabımı baxın. Və, əlbəttə, öz tətbiqini verərək === , xüsusi case semantiklər əldə edə bilərsiniz.

eql? - Hash bərabərliyi

eql? metodu eql? objother eyni hash düyməsinə müraciət edərsə, doğru qaytarır. Bu, üzvləri bərabərlik üçün yoxlamaq üçün istifadə olunur. Sinif obyektləri üçün Object , eql? == üçün sinonimdir. eql? bu ənənəni davam eql? onların köklü üsulu == , lakin istisnalar var. Məsələn, nümunə, == ilə növü dönüşüm yerinə yetirmək üçün, lakin eql? ilə eql? Buna görə:

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

Beləliklə, öz məqsədləriniz üçün yenidən təyin edə bilərsiniz və ya == redefine və alias :eql? :== istifadə edin alias :eql? :== alias :eql? :== Belə ki, hər iki üsul eyni şəkildə hərəkət edir.

equal? - şəxsiyyət müqayisə

== fərqli olaraq, equal? üsul equal? alt siniflər tərəfindən heç vaxt yenidən müəyyən edilməməlidir: bir obyektin şəxsiyyətini müəyyənləşdirmək üçün istifadə olunur (yəni, a.equal?(b) iff b ) b ).

Bu effektiv göstərici müqayisəsidir.

728
23 авг. cavab cümə axşamı 23 avqustda verilir . 2011-08-23 09:25 '11 'də saat 09:25 ' da 2011-08-23 09:25

Mən jtbandes cavab istəyirəm, lakin olduqca uzun olduğundan, mən öz kompakt cavab əlavə edəcəyik:

== , === , eql? equal?
4 müqayisə edici, yəni. Ruby'də 2 obyekti müqayisə etmək üçün 4 yol.
Ruby-də olduğu kimi, bütün komparatorlar (və əksər operatorlar) həqiqətən metod çağırışlarıdır; bu müqayisə üsullarının semantikasını dəyişə bilərsiniz, yenidən yaza və müəyyən edə bilərsiniz. Lakin, bir müqayisəçi daxili Ruby dilinin quruluşlarında istifadə edildikdə anlamaq vacibdir:

== (dəyər müqayisəsi)
Ruby istifadə edir: == hər yerdə, məsələn, iki obyektin dəyərlərini müqayisə etmək. Hash dəyərləri:

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

=== (vəziyyət müqayisə)
Ruby istifadə edir: === vəziyyətdə / quruluşda. Aşağıdakı kod snippetləri məntiqi olaraq eynidır:

 case foo when bar; p 'do something' end if bar === foo p 'do something' end 
border=0

eql? (hash düymələrinin müqayisəsi)
Ruby istifadə edir: eql? (hash metodu ilə birlikdə) hash düymələrini müqayisə etmək üçün. Ən siniflərdə: eql? ilə: ==.
Məlumat: eql? Öz xüsusi siniflərinizi yaratmaq istədiyiniz zaman vacibdir:

 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 

Qeyd Yaygın olaraq istifadə edilən bir Ruby sinif dəsti də bir hash key müqayisə əsaslanır.

equal? (obyektlərin şəxsiyyətinin müqayisəsi)
Ruby istifadə edir: bərabərdir? iki obyektin eyni olub olmadığını yoxlamaq üçün. Bu metod (class BasicObject sinfi) yazılmamalıdır.

 obj = obj2 = 'a' obj.equal? obj2 # => true obj.equal? obj.dup # => false 
41
06 апр. Andreas Rayo Kniep tərəfindən verilmiş cavab 06 Apr. 2015-04-06 03:42 '15 at 3:42 'de 2015-04-06 03:42

Bərabərlik operatorları: == və! =

Həm bərabərlik, həm də ikili bərabərlik kimi tanınan == operator, hər iki obyekt bərabər və yanlış olduqda səhv olur.

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

Operator! =, AKA və ya bang-tilde bərabərsizliyi, ==. Hər iki obyekt bərabər olmadıqda və bərabər olduqda yalançı olduqda doğru olur.

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

Eyni elementləri fərqli bir sıraya malik olan iki dizinin bərabər olmadığını, eyni məktubun böyük və kiçik versiyalarının bərabər olmadığını və s.

Farklı növlərin (məsələn, tam və float) nömrələrini müqayisə edərkən, onların ədədi dəyəri eynidırsa, == doğru qaytarır.

 2 == 2.0 # Output: => true 

Hər halda

Hər iki əməliyyatın bərabər olub olmadığını yoxlayan = operatordan fərqli olaraq, bu iki əmr eyni obyektə aid olub-olmadığını yoxlayır. Ruby'də ən bərabərlik formasıdır.

Məsələn: a = "zen" b = "zen"

 a.object_id # Output: => 20139460 b.object_id # Output :=> 19972120 a.equal? b # Output: => false 

Yuxarıdakı nümunədə eyni dəyəri olan iki simli var. Lakin, onlar müxtəlif obyekt identifikatorları olan iki fərqli obyektdir. Buna görə, bərabərdir? üsul yanlış qaytarır.

Yenidən cəhd edin, yalnız bu dəfə b bir istinad olacaq. Eyni obyektə işarə etdiyindən obyektin identifikatorunun hər iki dəyişən üçün eyni olduğunu nəzərə alaraq.

 a = "zen" b = a a.object_id # Output: => 18637360 b.object_id # Output: => 18637360 a.equal? b # Output: => true 

EQL?

Hash sinifində ifadə eql? Metod bərabərlik üçün açarları doğrulamak üçün istifadə olunur. Bəzi fon bunu izah etmək məcburiyyətindədir. Hesaplamanın ümumi kontekstində, hash funksiyası hər hansı bir ölçünün bir simli (və ya faylını) alır və bir hashcode adlanan bir sabit ölçülü simli və ya tamsayı yaradır, adətən yalnız bir hash deyilir. Haşin kodlarının bir çoxu istifadə olunan MD5, SHA-1 və CRC tipləridir. Şifrələmə alqoritmləri, məlumat bazasının indeksləşdirilməsi, faylların bütövlüyünü yoxlamaq və s. Ruby kimi bəzi proqramlaşdırma dilləri, hash masası adlı bir kolleksiya növü təmin edir. Hash masaları, unikal düymələrdən və onların müvafiq dəyərlərindən ibarət cütləri məlumatları saxlayan lüğət kolleksiyalarıdır. Başlıq altında bu düymələr hash kodları kimi saxlanılır. Hash masaları adətən sadəcə xeyir adlanır. Söz haşının bir hash koduna və ya hash masasına necə istinad edə biləcəyinə diqqət yetirin. Ruby proqramlaşdırma kontekstində, hash sözü demək olar ki, həmişə bir lüğət kolleksiyasına aiddir.

Ruby, hash kodları yaratmaq üçün hash adlı daxili bir üsul təmin edir. Aşağıdakı misalda bir simli alır və bir hash kodunu qaytarır. Müxtəlif obyektlər (fərqli obyektin identifikatorları ilə) olmasına baxmayaraq eyni dəyəri olan xətləri həmişə eyni hash koduna sahib olduğunu unutmayın.

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

Hash metodu, bütün Ruby obyektlərinin köklü kökləri olan Object sinifinə daxil olan Kernel modulunda tətbiq olunur. Symbol və Tamsayı kimi bəzi dərslər, standart tətbiqi, digərləri, məsələn, String və Hash kimi istifadə edir, öz tətbiqlərini təmin edir.

 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 

Ruby'də, hash (toplama) bir şey saxlamaq zaman, bir əsas kimi təqdim bir obyekt (məsələn, bir string və ya xarakter) bir hash kodu kimi çevrilir və saxlanılır. Daha sonra, hash (toplama) bir maddə almaq zaman, obyekt bir hash kodu çevrilir və mövcud düymələri ilə müqayisə bir əsas kimi təmin edir. Bir matç varsa, müvafiq elementin dəyəri qaytarılır. Müqayisə başlıq altında tənlik metodundan istifadə edilir.

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

Çox hallarda, tənlik metodu == metoduna bənzər davranır. Ancaq bir neçə istisna var. Məsələn, eql? bir şamandıra ilə müqayisə edərkən örtük tipli konversiya etməz.

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

Case bərabərliyi operatoru: ===

String, Range və Regexp kimi daxili Ruby siniflərindən bir çoxu, eyni zamanda, bərabər, üçlü bərabər və üçqual kimi tanınan öz === operator tətbiqlərini təmin edir. Hər sinifdə fərqli şəkildə tətbiq olunduğundan, o, adlandırılan obyektin növündən asılı olaraq fərqlənir. Sağdakı obyekt "sol" olan obyektin "aiddir" və ya "bir üzvü" olduqda, tipik olaraq doğru olur. Məsələn, bir obyektin bir sinifin nümunəsi olub-olmadığını yoxlamaq üçün istifadə edə bilərsiniz (ya da onun alt siniflərindən biri).

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

Eyni nəticə, iş üçün uyğun olan digər metodlardan istifadə edilə bilər. Səmərəliliyin və qısqanclıqdan qurtulmadan mümkün olduğu qədər aydın şəkildə oxunması asan olan kodu yazmaq daha yaxşıdır.

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

Sonuncu nümunə yalançı olur, çünki 2 kimi tamsaytlar Classname Təminatın bir alt sinfi olan Fixnum sinifidir. ===, is_a? və instance_of? Əgər obyekt bu sinif və ya hər hansı bir alt sinifin bir nümunəsidirsə, üsullar doğru olur. Example_of metodu daha sərtdir və obyekt bu dəqiq sinifin bir nümunəsidir və bir alt sinif deyilsə, doğru olur.

is_a? və kind_of? Nümunə sinfi ilə qarışan Kernel modulunda üsullar tətbiq olunur. Hər ikisi də eyni metoddan ibarətdir. Onu yoxlayın:

Kernel.instance_method (: kind_of?) == Kernel.instance_method (: is_a?) # Çıxış: => true

İmplant aralığı ===

=== Operator bir sıra obyektdə çağırıldığında, sağdakı dəyər solda aralığında olduqda doğru olur.

 (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 

=== Operatorun sol obyekt üçün === üsulunu çağırdığını unutmayın. Beləliklə, (1..4) === 3 (1..4) ilə bərabərdir. Digər bir deyişlə, sol operandın sinfi === əməliyyatın tətbiqinin operandın mövqeləri bir-birinin ardınca gəlməyəcəyini təyin edəcəkdir.

Yeniləmə Regexp ===

Sağdakı xətt solda olan müntəzəm ifadəyə uyğun gəlsə düzgün olur. / zen / === "Zazen bugün praktik" Sonuç: => true # "praktik zazen today" = ~ / zen /

Gizli operator istifadə etmək üçün === halda / ifadələr

Bu bəyanat, iddialar / iddialar üçün başlıq altında da istifadə olunur. Onun ən çox istifadə etdiyi bu.

 minutes = 15 case minutes when 10..20 puts "match" else puts "no match" end # Output: match 

Yuxarıdakı nümunədə, Ruby örtük olaraq cüt bərabər (==) bir operator istifadə edərsə, 10..20 aralığında bir tamsayıya bərabər sayılmayacaq, məsələn, 15. Üç ünsiyyət operatoru (== =) bütün operatorlarda halda / zaman. Yuxarıdakı nümunədə verilən kod aşağıdakılara bərabərdir:

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

Nümunə uyğun operatorlar: = ~ və! ~

Operatorlar = ~ (bərabər-tilde) və! ~ (bang-tilde) simvol və simvolları düzgün ifadə nümunələri ilə uyğunlaşdırmaq üçün istifadə olunur.

String və sembol sinfində = ~ metodunun həyata keçirilməsi müntəzəm bir ifadəni (Regexp sinifinin nümunəsi) bir arqument kimi qəbul edir.

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

Regexp sinifində bir tətbiq bir dəlil kimi simli və ya xarakter gözləyir.

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

Bütün tətbiqlərdə, bir simli və ya xarakter Regexp deseniyle eşleştiğinde, matçın konumunu (endeksi) bir tamsayı verir. Heç bir matç yoxsa, nil qaytarır. Ruby'də hər hansı tamsayı dəyərinin "doğru" olduğunu və nilin "yalan" olduğunu unutmayın, buna görə = ~ operator operatorlar üçün açıqlamalar və üçlü ifadələrlə istifadə edilə bilər.

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

Nümunə uyğunlaşdırma operatorları hesabatların qısaldılmış yazılması üçün də faydalıdır. Məsələn:

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

Operator! ~ əleyhinə = ~, heç bir uyğunlaşma yoxdursa, doğru olub və bir oyun varsa yalançı olur.

Əlavə məlumat bu blog yazısında mövcuddur.

25
29 мая '16 в 19:47 2016-05-29 19:47 Cavab BrunoFacca tərəfindən verilir 29 may '16 saat 19:47 2016-05-29 19:47

=== # - Equivalent Equality

== # --- ümumi bərabərlik

həm də eyni şəkildə çalışırlar, amma "===" hətta ifadələr hazırlayırlar

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

bir fərq var

 String === "test" #=> true String == "test" #=> false 
7
22 апр. Cavab 22 martda Kishore Mohan tərəfindən verilir 2014-04-22 12:13 '14 at 12:13 2014-04-22 12:13

Ruby, bərabərliyi idarə etmək üçün bir neçə müxtəlif üsul təqdim edir:

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

Bu, başqalarına kömək edir.

6
11 апр. Cavab kalibbala 11 apr verilir . 2015-04-11 23:43 '15 at 23:43 2015-04-11 23:43

Mən operatoru === genişləndirmək istərdim.

=== bir bərabərlik operatoru deyil!

yox

Mənə bu nöqtəni həqiqətən verin.

Javascript və PHP-də bərabərlik operatoru olaraq === ilə tanış ola bilərsiniz, lakin bu Ruby-də bərabərlik operatoru deyil və əsasən fərqli semantiklərə malikdir.

Beləliklə === nədir?

=== - Şablon uyğunluq operatoru!

  • === müntəzəm ifadələrlə eşleşir
  • === nəzarət edir
  • === sinif nümunəsini yoxlayır
  • === Lambda ifadəsinə səbəb olur
  • === bəzən bərabərliyi sınayır, amma əsasən də yox

Beləliklə, bu dəlilik mənada nədir?

  • Enumerable#grep istifadə === Daxili Operatorlar
  • istifadə case when === daxili
  • Fun fakt, rescue === daxili istifadə edir

Buna görə ifadəni istifadə case when müntəzəm ifadələrdən, dərslərdən və aralıklardan, hətta lambda ifadələrindən istifadə edə bilərsiniz.

Bəzi nümunələr

 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 

Bütün bu nümunələr həmçinin pattern === value ilə də işləyir və grep metodundan istifadə edir.

 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] 
4
12 марта '17 в 5:02 2017-03-12 05:02 cavab 12 mart '17 'da 5:02 2017-03-12 05:02' də akuhn tərəfindən verilir

Yuxarıda qeyd olunanların hamısı üçün sadə bir test yazdım.

 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) 
-8
26 апр. Cavab 26 Mayda Tom Phan tərəfindən verildi 2014-04-26 02:02 '14 da 2:02 2014-04-26 02:02

Tags ilə bağlı digər suallar yaxud sual