sự khác nhau của == , ===, eql?, equal? trong so sánh và sự khác nhau của << & += trong việc nối string
Bài đăng này đã không được cập nhật trong 9 năm
1.Sự Khác Nhau Của == , ===, Eql?, Equal? Trong So Sánh
-
Điểm giống nhau cơ bản giữa chúng là chúng đều dùng để so sánh và trả về giá trị là true hoặc false.
-
==
— generic equality: So sánh có cùng giá trị hay không. Đây là cách so sánh phổ biến và cơ bản nhất trong hầu hết các ngôn ngữ lập trình. -
===
—Case
equality: Như tên gọi của nó,===
là so sánh dạng case. Các điều kiện của case sẽ đc implement với mỗi class tương ứng. Ví dụ với:- Range
- Regex
- Proc (in Ruby 1.9)
Thì case sẽ như sau:
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
(1..5) === 3 # => true
(1..5) === 6 # => false
Integer === 42 # => true
Integer === 'fourtytwo' # => false
/ell/ === 'Hello' # => true
/ell/ === 'Foobar' # => false
Ta cùng xem tiếp ví dụ sau:
"a" === "b" # false # different values, different objects
"a" === "a" # true # same values
Như vậy `===` cũng đơn thuần là so sánh giá trị chứ không phải là so sánh object có điều nó dùng `case` để so sánh và `===` còn được gọi là `Case equality`.
"test" == "test" #=> true
"test" === "test" #=> true
#
#sự khác nhau giữa == và === là ở đây
String === "test" #=> true
String == "test" #=> false
-
Eql?
—Hash
equality: Method này sẽ trả vềtrue
nếu 2 tham số có cùnghash key
. Nó sử dụngHash
để kiểm tra cácmember
có giống nhau hay không. VớiObject
thìEql?
giống như==
(chỉ so sánh value) và hầu hết cácsubclasses
cũng như vậy.Tuy nhiên với kiểu
Numeric
thì có ngoại lệ, nó chỉ kiểm tra 2 tham số có cùng giá trị và cùng Class hay không.Ví dụ:
1 == 1.0 #=> true | vì == chỉ so sánh giá trị
1.eql? 1.0 #=> false | vì chúng khác Class
1.class #=> Fixnum
1.0.class #=> Float
-
Equal?
— So sánh giá trị vàobject_id
củaobject
.object_id
là method trả về định danh của đối tượng. Nếu hai đối tượng có chung một
object_id
thì chúng giống nhau tức là đều trỏ đến cùng một đối tượng trong vùng nhớ và ngược lại.
`Equal?` là cách hiệu quả để so sánh con trỏ, dùng để kiểm tra chính xác xem có cùng là 1 `Object` hay không. để hiểu rõ hơn ta xem ví dụ sau:
2.1.0 :001 > a = "viblo.asia"
2.1.0 :002 > b = "viblo.asia"
2.1.0 :003 > c = d = "viblo.asia"
2.1.0 :004 > a.equal?b # false
2.1.0 :005 > c.equal?d # true
Bây giờ ta cùng xem object_id
của chúng
2.1.0 :005 > a.object_id # 19088820
2.1.0 :007 > b.object_id # 19008500
2.1.0 :008 > c.object_id # 18854700
2.1.0 :009 > d.object_id # 18854700
Ta thấy c
và d
có cùng object_id
là 18854700
và kết quả trả về là false
.
Như vậy `Equal?` sẽ so sánh cả `object_id` nên mặc dù value của `a, b, c, d` cùng là `viblo.asia` nhưng chúng có `object_id` khác nhau dẫn đến kết quả trả về là `false`.
2.Sự khác nhau của << & += trong việc nối chuỗi
- Nối chuỗi với
+=
2.1.0 :010 > first_name = "Viblo"
2.1.0 :011 > name = first_name
2.1.0 :012 > last_name = "Asia"
2.1.0 :013 > name += last_name
2.1.0 :014 > name # VibloAsia
2.1.0 :015 > first_name # Viblo
Với ví dụ trên thì kết quả như bình thường. Không có gì phải bàn cãi
- Nối chuỗi với
<<
2.1.0 :010 > first_name = "Viblo"
2.1.0 :011 > name = first_name
2.1.0 :012 > last_name = "Asia"
2.1.0 :013 > name << last_name
2.1.0 :014 > name # VibloAsia
2.1.0 :015 > first_name # VibloAsia
Ta đã thấy sự khác biệt. Vì sao lại có kết quả như vậy?
Chúng ta sẽ kiểm tra object_id
của name
, first_name
2.1.0 :016 > name.object_id --> 15533700
2.1.0 :017 > first_name.object_id --> 15533700
Phép gán name = first_name
lúc này name & first_name có cùng 1 object_id và khi thực hiện:
- `<<` sẽ xử lý trực tiếp trên object của nó, vì vậy khi name thay đổi thì `first_name` cũng thay đổi theo.
- `+=` sẽ tạo ra một object mới sau khi thực hiện cộng chuỗi xong mới gán lại giá trị cho object cũ(nghe qua đã thấy có vẻ nó chậm hơn rồi ^^), vì vậy khi thay đổi name thì `first_name` không bị ảnh hưởng.
- Chúng ta cùng sử dụng
benchmark
để xem thời gian thực hiện của 2 cách này:
require 'benchmabash
n = 10000
Benchmark.bm do |benchmark|
benchmark.report("+=") do
n.times do
first_name = "Viblo"
name = first_name
last_name = "Asia"
name += last_name
end
end
benchmark.report("<<") do
n.times do
first_name = "Viblo"
name = first_name
last_name = "Asia"
name << last_name
end
end
end
Kết quả:
user system total real
+= 0.010000 0.000000 0.010000 ( 0.007283)
<< 0.000000 0.000000 0.000000 ( 0.004042)
Qua đó mình thấy được tốc độ xử lý của <<
sẽ nhanh hơn +=
. Đây cũng chính là lý do <<
được sử dụng phổ biến hơn
3.Kết luận
Trên đây là 1 số chia sẻ trong quá trình tìm hiểu của mình. Mong rằng sẽ giúp ích được phần nào cho các bạn. Happy coding
All rights reserved