Sự khác biệt giữa bằng nhau là gì?, Eql?, === và ==?


552

Tôi đang cố gắng để hiểu sự khác biệt giữa bốn phương pháp này. Tôi biết theo mặc định ==gọi phương thức equal?trả về true khi cả hai toán hạng tham chiếu chính xác cùng một đối tượng.

===theo mặc định cũng gọi ==mà các cuộc gọi equal?... okay, vì vậy nếu cả ba phương pháp này không được ghi đè, sau đó tôi đoán ===, ==equal?thực hiện chính xác những điều tương tự?

Bây giờ đến eql?. Điều này làm gì (theo mặc định)? Nó có thực hiện cuộc gọi đến hàm băm / id của toán hạng không?

Tại sao Ruby có nhiều dấu hiệu bình đẳng? Họ có nghĩa vụ phải khác nhau về ngữ nghĩa?


Tôi chỉ mới bắt đầu một IRB và đã có kết quả sau đó mâu thuẫn với bạn ... Tất cả những 3 là đúng: "a" == "a", "a" === "a""a".eql? "a". Nhưng điều này là sai: "a".equal? "a"(Của tôi là ruby ​​1.9.2-
p180

7
@Peter: Đó là vì các chuỗi ghi đè tất cả các toán tử đẳng thức. Cố gắng sử dụng a = Object.new; b = Object.newthì tất cả ==, ===, .equal?, .eql?sẽ trả lại truecho avs avà sai cho avs b.
Nemo157

Câu trả lời:


785

Tôi sẽ trích dẫn rất nhiều tài liệu về Object ở đây, vì tôi nghĩ nó có một số giải thích tuyệt vời. Tôi khuyến khích bạn đọc nó và cả tài liệu cho các phương thức này khi chúng bị ghi đè trong các lớp khác, như String .

Lưu ý bên lề: nếu bạn muốn tự mình thử những thứ này trên các đối tượng khác nhau, hãy sử dụng một cái gì đó như thế này:

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}

== - "bình đẳng" chung

Ở cấp độ Đối tượng, chỉ ==trả về true nếu objotherlà cùng một đối tượng. Thông thường, phương thức này được ghi đè trong các lớp con cháu để cung cấp ý nghĩa cụ thể của lớp.

Đây là so sánh phổ biến nhất, và do đó, nơi cơ bản nhất mà bạn (với tư cách là tác giả của một lớp) có thể quyết định xem hai đối tượng có "bằng nhau" hay không.

=== - bình đẳng trường hợp

Đối với lớp Object, có hiệu quả tương tự như cách gọi #==, nhưng thường được ghi đè bởi con cháu để cung cấp ngữ nghĩa có ý nghĩa trong các câu lệnh tình huống.

Điều này là vô cùng hữu ích. Ví dụ về những điều có ===triển khai thú vị :

  • Phạm vi
  • Regex
  • Proc (trong Ruby 1.9)

Vì vậy, bạn có thể làm những việc như:

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

Xem câu trả lời của tôi ở đây để biết ví dụ gọn gàng về cách case+ Regexcó thể làm cho mã sạch hơn rất nhiều. Và tất nhiên, bằng cách cung cấp ===triển khai của riêng bạn, bạn có thể có được casengữ nghĩa tùy chỉnh .

eql?- Hashbình đẳng

Các eql?phương thức trả về đúng nếu objothertham khảo các khóa băm cùng. Điều này được sử dụng Hashđể kiểm tra các thành viên cho sự bình đẳng. Đối với các đối tượng của lớp Object, eql?là đồng nghĩa với ==. Các lớp con thường tiếp tục truyền thống này bằng cách đặt bí danh eql?cho ==phương thức ghi đè của chúng , nhưng vẫn có ngoại lệ. Numericcác loại, ví dụ, thực hiện chuyển đổi loại qua ==, nhưng không qua eql?, vì vậy:

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

Vì vậy, bạn có thể ghi đè điều này cho mục đích sử dụng của riêng bạn hoặc bạn có thể ghi đè ==và sử dụng alias :eql? :==để hai phương thức hoạt động theo cùng một cách.

equal? - so sánh danh tính

Không giống như ==, equal?phương thức không bao giờ bị ghi đè bởi các lớp con: nó được sử dụng để xác định danh tính đối tượng (nghĩa là, a.equal?(b)iff alà cùng một đối tượng như b).

Đây là so sánh con trỏ hiệu quả.


32
Theo tôi hiểu từ câu trả lời của bạn, sự nghiêm ngặt là: bằng nhau? <eql? <== <===. Thông thường, bạn sử dụng ==. Đối với một số mục đích lỏng lẻo, bạn sử dụng ===. Đối với tình huống nghiêm ngặt, bạn sử dụng eql?, Và để nhận dạng hoàn chỉnh, bạn sử dụng bằng?.
sawa

21
Khái niệm về sự nghiêm ngặt không được thi hành hoặc thậm chí được đề xuất trong tài liệu, nó chỉ xảy ra mà Numericxử lý nó theo cách chặt chẽ hơn ==. Nó thực sự phụ thuộc vào tác giả của lớp. ===được sử dụng không thường xuyên bên ngoài các casebáo cáo.
jtbandes

4
== là sự bình đẳng về mặt lớn hơn / nhỏ hơn. Tức là, nếu bạn bao gồm So sánh, nó sẽ được xác định theo nghĩa <=> trả về 0. Đây là lý do tại sao 1 == 1.0 trả về đúng.
apeiros

5
@sawa Tôi thường nghĩ ===là "khớp" (đại khái). Như trong "regex khớp với chuỗi" hay "phạm vi khớp với (bao gồm) số".
Kelvin

7
Sự thật thú vị: các tài liệu chính thức hiện liên kết đến câu trả lời này (xem ruby-doc.org/core-2.1.5/ mẹo ).
Đánh dấu Amery

46

Tôi thích câu trả lời của jtbandes, nhưng vì nó khá dài, tôi sẽ thêm câu trả lời nhỏ gọn của riêng mình:

==, ===, eql?,equal?
4 bộ so sánh, tức là. 4 cách để so sánh 2 đối tượng, trong Ruby.
Vì, trong Ruby, tất cả các bộ so sánh (và hầu hết các toán tử) thực sự là các lệnh gọi phương thức, bạn có thể thay đổi, ghi đè và xác định ngữ nghĩa của các phương thức so sánh này. Tuy nhiên, điều quan trọng là phải hiểu, khi các cấu trúc ngôn ngữ nội bộ của Ruby sử dụng bộ so sánh nào:

==(so sánh giá trị)
Ruby sử dụng: == ở mọi nơi để so sánh giá trị của 2 đối tượng, vd. Giá trị băm:

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

===(so sánh trường hợp)
Ruby sử dụng: === trong trường hợp / khi các cấu trúc. Các đoạn mã sau giống hệt nhau về mặt logic:

case foo
  when bar;  p 'do something'
end

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

eql?(So ​​sánh khóa băm)
Ruby sử dụng: eql? (kết hợp với phương thức băm) để so sánh các khóa Hash. Trong hầu hết các lớp: eql? trùng với: ==.
Kiến thức về: eql? chỉ quan trọng khi bạn muốn tạo các lớp đặc biệt của riêng mình:

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

Lưu ý: Bộ Ruby-class thường được sử dụng cũng dựa trên so sánh Hash-key.

equal?(so sánh nhận dạng đối tượng)
Ruby sử dụng: bằng nhau? để kiểm tra xem hai đối tượng có giống nhau không. Phương thức này (của lớp BasicObject) không được ghi đè.

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

30
Đó là một câu trả lời tốt, nhưng nó gần như dài bằng jtbandes. :)
kỳ lạ

2
@odigity, dài khoảng 70%. Tôi có thể nghĩ ra nhiều thứ để chi 30% đó.
Cary Swoveland

Tôi nghĩ rằng ví dụ về eql?là rất sai lệch. eql?là một so sánh bình đẳng phù hợp với cách tính băm, nghĩa là a.eql?(b)đảm bảo điều đó a.hash == b.hash. Nó không chỉ đơn giản là so sánh các mã băm.
Andrey Tarantsov

trường hợp so sánh thực sự tương đương bar === foovà không foo === bar? Tôi hy vọng điều sau là đúng và nó rất quan trọng vì trình biên dịch gọi phía bên trái: === `'
Alexis Wilke

Theo như tôi biết, đó là bar === foo: Ruby sử dụng giá trị trường hợp ở phía bên trái và biến trường hợp ở phía bên tay phải. Điều này có thể phải làm với việc tránh các NPE (Ngoại lệ con trỏ Null).
Andreas Rayo Kniep

34

Toán tử bình đẳng: == và! =

Toán tử ==, còn được gọi là đẳng thức hoặc gấp đôi bằng nhau, sẽ trả về true nếu cả hai đối tượng đều bằng nhau và sai nếu không.

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

Toán tử! =, Còn được gọi là bất đẳng thức, ngược lại với ==. Nó sẽ trả về true nếu cả hai đối tượng không bằng nhau và sai nếu chúng bằng nhau.

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

Lưu ý rằng hai mảng có cùng các phần tử theo thứ tự khác nhau không bằng nhau, các phiên bản chữ hoa và chữ thường của cùng một chữ cái không bằng nhau, v.v.

Khi so sánh các số của các loại khác nhau (ví dụ: số nguyên và số float), nếu giá trị số của chúng là như nhau, == sẽ trả về giá trị true.

2 == 2.0 # Output: => true

công bằng?

Không giống như toán tử == kiểm tra xem cả hai toán hạng có bằng nhau không, phương thức bằng nhau kiểm tra nếu hai toán hạng tham chiếu đến cùng một đối tượng. Đây là hình thức bình đẳng nghiêm ngặt nhất trong Ruby.

Ví dụ: a = "zen" b = "zen"

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

a.equal? b  # Output: => false

Trong ví dụ trên, chúng ta có hai chuỗi có cùng giá trị. Tuy nhiên, chúng là hai đối tượng riêng biệt, có ID đối tượng khác nhau. Do đó, bằng nhau? phương thức sẽ trả về false.

Hãy thử lại, chỉ lần này b sẽ là một tham chiếu đến a. Lưu ý rằng ID đối tượng là giống nhau cho cả hai biến, vì chúng trỏ đến cùng một đối tượng.

a = "zen"
b = a

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

a.equal? b  # Output: => true

e ngại?

Trong lớp Hash, eql? phương pháp này được sử dụng để kiểm tra các khóa cho sự bình đẳng. Một số nền tảng được yêu cầu để giải thích điều này. Trong ngữ cảnh chung của điện toán, hàm băm lấy một chuỗi (hoặc tệp) có kích thước bất kỳ và tạo ra một chuỗi hoặc số nguyên có kích thước cố định được gọi là mã băm, thường được gọi là chỉ băm. Một số loại mã băm thường được sử dụng là MD5, SHA-1 và CRC. Chúng được sử dụng trong các thuật toán mã hóa, lập chỉ mục cơ sở dữ liệu, kiểm tra tính toàn vẹn của tệp, v.v ... Một số ngôn ngữ lập trình, như Ruby, cung cấp một loại bộ sưu tập được gọi là bảng băm. Các bảng băm là các bộ sưu tập giống như từ điển lưu trữ dữ liệu theo cặp, bao gồm các khóa duy nhất và các giá trị tương ứng của chúng. Dưới mui xe, các khóa đó được lưu trữ dưới dạng mã băm. Bảng băm thường được gọi là chỉ băm. Lưu ý cách từ hashcan đề cập đến mã băm hoặc bảng băm.

Ruby cung cấp một phương thức tích hợp được gọi là hàm băm để tạo mã băm. Trong ví dụ dưới đây, nó lấy một chuỗi và trả về mã băm. Lưu ý cách các chuỗi có cùng giá trị luôn có cùng mã băm, mặc dù chúng là các đối tượng riêng biệt (có ID đối tượng khác nhau).

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

Phương thức băm được triển khai trong mô-đun Kernel, được bao gồm trong lớp Object, là gốc mặc định của tất cả các đối tượng Ruby. Một số lớp như Biểu tượng và Số nguyên sử dụng triển khai mặc định, các lớp khác như Chuỗi và Hash cung cấp các triển khai riêng của chúng.

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

Trong Ruby, khi chúng ta lưu trữ thứ gì đó trong hàm băm (bộ sưu tập), đối tượng được cung cấp dưới dạng khóa (ví dụ: chuỗi hoặc ký hiệu) được chuyển đổi thành và được lưu trữ dưới dạng mã băm. Sau này, khi truy xuất một phần tử từ hàm băm (bộ sưu tập), chúng tôi cung cấp một đối tượng dưới dạng khóa, được chuyển đổi thành mã băm và so sánh với các khóa hiện có. Nếu có sự trùng khớp, giá trị của mục tương ứng được trả về. Việc so sánh được thực hiện bằng cách sử dụng eql? phương pháp dưới mui xe.

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

Trong hầu hết các trường hợp, các eql? phương thức hoạt động tương tự như phương thức ==. Tuy nhiên, có một vài trường hợp ngoại lệ. Ví dụ, eql? không thực hiện chuyển đổi kiểu ngầm định khi so sánh một số nguyên với một số float.

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

Toán tử bình đẳng trường hợp: ===

Nhiều lớp dựng sẵn của Ruby, chẳng hạn như String, Range và Regapi, cung cấp các triển khai riêng của toán tử ===, còn được gọi là đẳng thức trường hợp, ba bằng hoặc ba phần. Bởi vì nó được triển khai khác nhau trong mỗi lớp, nên nó sẽ hoạt động khác nhau tùy thuộc vào loại đối tượng mà nó được gọi. Nói chung, nó trả về true nếu đối tượng bên phải "thuộc về" hoặc "là thành viên của" đối tượng bên trái. Ví dụ, nó có thể được sử dụng để kiểm tra nếu một đối tượng là một thể hiện của một lớp (hoặc một trong các lớp con của nó).

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

Kết quả tương tự có thể đạt được với các phương pháp khác có lẽ phù hợp nhất cho công việc. Thông thường tốt hơn là viết mã dễ đọc bằng cách rõ ràng nhất có thể, mà không làm giảm hiệu quả và tính đồng nhất.

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

Lưu ý ví dụ cuối cùng trả về false vì các số nguyên như 2 là các thể hiện của lớp Fixnum, là một lớp con của lớp Integer. ===, is_a? và instance_of? các phương thức trả về true nếu đối tượng là một thể hiện của lớp đã cho hoặc bất kỳ lớp con nào. Phương thức instance_of chặt chẽ hơn và chỉ trả về true nếu đối tượng là một thể hiện của lớp chính xác đó, không phải là một lớp con.

Đó là? và kind_of? các phương thức được triển khai trong mô-đun Kernel, được trộn bởi lớp Object. Cả hai đều là bí danh cho cùng một phương thức. Hãy xác minh:

Kernel.instance_method (: kind_of?) == Kernel.instance_method (: is_a?) # Kết quả: => true

Phạm vi thực hiện ===

Khi toán tử === được gọi trên một đối tượng phạm vi, nó sẽ trả về true nếu giá trị bên phải nằm trong phạm vi bên trái.

(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

Hãy nhớ rằng toán tử === gọi phương thức === của đối tượng bên trái. Vì vậy (1..4) === 3 tương đương với (1..4). === 3. Nói cách khác, lớp của toán hạng bên trái sẽ xác định việc thực hiện phương thức === nào được gọi, vì vậy các vị trí toán hạng không thể thay thế cho nhau.

Thực hiện Regex của ===

Trả về true nếu chuỗi bên phải khớp với biểu thức chính quy bên trái. / zen / === "thực hành zazen ngay hôm nay" # Kết quả: => true # giống như "thực hành zazen ngày hôm nay" = ~ / zen /

Việc sử dụng ngầm định toán tử === trong trường hợp / khi các câu lệnh

Toán tử này cũng được sử dụng dưới mui xe trong trường hợp / khi báo cáo. Đó là cách sử dụng phổ biến nhất của nó.

minutes = 15

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

# Output: match

Trong ví dụ trên, nếu Ruby đã ngầm sử dụng toán tử kép bằng (==), thì phạm vi 10..20 sẽ không được coi là bằng một số nguyên như 15. Chúng khớp với nhau vì toán tử ba bằng (===) là ngầm sử dụng trong tất cả các trường hợp / khi báo cáo. Mã trong ví dụ trên tương đương với:

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

Toán tử khớp mẫu: = ~ và! ~

Các toán tử = ~ (bằng nhau) và! ~ (Bang-tilde) được sử dụng để khớp các chuỗi và ký hiệu chống lại các mẫu biểu thức chính quy.

Việc triển khai phương thức = ~ trong các lớp Chuỗi và Biểu tượng mong muốn một biểu thức chính quy (một thể hiện của lớp Regapi) làm đối số.

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

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

Việc triển khai trong lớp Regapi mong muốn một chuỗi hoặc một ký hiệu làm đối số.

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

Trong tất cả các triển khai, khi chuỗi hoặc ký hiệu khớp với mẫu Regapi, nó sẽ trả về một số nguyên là vị trí (chỉ mục) của kết quả khớp. Nếu không có kết quả khớp, nó sẽ trả về nil. Hãy nhớ rằng, trong Ruby, bất kỳ giá trị số nguyên nào là "truey" và nil là "falsy", do đó toán tử = ~ có thể được sử dụng trong câu lệnh if và toán tử ternary.

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

Toán tử khớp mẫu cũng hữu ích để viết các câu lệnh if ngắn hơn. Thí dụ:

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

Toán tử! ~ Ngược lại với = ~, nó trả về true khi không có kết quả khớp và sai nếu có khớp.

Thêm thông tin có sẵn tại bài viết blog này .


6
Tôi thấy đây là một câu trả lời tốt hơn câu trả lời hiện đang được chấp nhận, vì nó cung cấp các ví dụ hay và ít mơ hồ về ý nghĩa của các loại bình đẳng khác nhau và lý do chúng tồn tại / nơi chúng được sử dụng.
Qqwy

1
Câu trả lời rất chi tiết, nhưng trên irb của tôi (ruby v 2.2.1) :zen === "zen"trả về sai
Mike R

@MikeR Cảm ơn bạn đã cho tôi biết. Tôi đã sửa câu trả lời.
BrunoFacca

Tôi nghĩ bạn có nghĩa là type_of? "Lưu ý ví dụ cuối cùng trả về sai vì các số nguyên như 2 là các thể hiện của lớp Fixnum, là lớp con của lớp Integer. ===, is_a? Và instance_of? (TYPE_OF?)"?
dùng1883793

1
Tôi thích câu trả lời này. Cảm ơn
Abdullah Fadhel

9

Ruby trưng bày một số phương pháp khác nhau để xử lý sự bình đẳng:

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.

Tiếp tục đọc bằng cách nhấp vào liên kết dưới đây, nó đã cho tôi một sự hiểu biết tóm tắt rõ ràng.

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

Hy vọng nó sẽ giúp người khác.


8

=== # --- trường hợp bình đẳng

== # --- bình đẳng chung

cả hai đều hoạt động tương tự nhưng "===" thậm chí làm các báo cáo trường hợp

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

ở đây sự khác biệt

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

3
Chúng không hoạt động tương tự nhau, mặc dù điều đó có xu hướng đúng khi a==bđó a===b. Nhưng a===bmạnh hơn nhiều. ===không đối xứng, và a===bcó nghĩa là một điều rất khác với b===a, nói gì đến a==b.
mwfearnley

8

Tôi muốn mở rộng trên các ===nhà điều hành.

=== không phải là một toán tử bình đẳng!

Không phải.

Hãy để điểm đó thực sự xuyên suốt.

Bạn có thể quen thuộc với ===tư cách là một toán tử đẳng thức trong Javascript và PHP, nhưng đây không phải là một toán tử đẳng thức trong Ruby và có ngữ nghĩa cơ bản khác nhau.

Vậy ===làm gì?

=== là toán tử khớp mẫu!

  • === phù hợp với biểu thức thông thường
  • === kiểm tra phạm vi thành viên
  • === kiểm tra là ví dụ của một lớp
  • === gọi biểu thức lambda
  • === đôi khi kiểm tra sự bình đẳng, nhưng chủ yếu là không

Vậy làm thế nào mà sự điên rồ này có ý nghĩa?

  • Enumerable#grepsử dụng ===nội bộ
  • case whenbáo cáo sử dụng ===nội bộ
  • Thực tế thú vị, rescuesử dụng ===nội bộ

Đó là lý do tại sao bạn có thể sử dụng các biểu thức và lớp và phạm vi thông thường và thậm chí các biểu thức lambda trong một case whencâu lệnh.

Vài ví dụ

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

Tất cả các ví dụ này làm việc với pattern === valuequá, cũng như với grepphương pháp.

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

Tôi đã viết một bài kiểm tra đơn giản cho tất cả các bên trên.

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.