Операторы равенства: == и! =
Оператор ==, также известный как равенство или двойное равенство, вернет истину, если оба объекта равны, и ложь, если они не равны.
"koan" == "koan" # Output: => true
Оператор! =, Также известный как неравенство, является противоположностью ==. Он вернет истину, если оба объекта не равны, и ложь, если они равны.
"koan" != "discursive thought" # Output: => true
Обратите внимание, что два массива с одинаковыми элементами в разном порядке не равны, версии одной и той же буквы в верхнем и нижнем регистре не равны и так далее.
При сравнении чисел разных типов (например, integer и float), если их числовое значение совпадает, == вернет true.
2 == 2.0 # Output: => true
равный?
В отличие от оператора ==, который проверяет, равны ли оба операнда, метод равенства проверяет, относятся ли два операнда к одному и тому же объекту. Это самая строгая форма равенства в Ruby.
Пример: a = "zen" b = "zen"
a.object_id # Output: => 20139460
b.object_id # Output :=> 19972120
a.equal? b # Output: => false
В приведенном выше примере у нас есть две строки с одинаковым значением. Однако это два разных объекта с разными идентификаторами. Значит, равный? метод вернет false.
Попробуем еще раз, только на этот раз b будет ссылкой на a. Обратите внимание, что идентификатор объекта одинаков для обеих переменных, поскольку они указывают на один и тот же объект.
a = "zen"
b = a
a.object_id # Output: => 18637360
b.object_id # Output: => 18637360
a.equal? b # Output: => true
eql?
В классе Hash команда eql? Метод используется для проверки ключей на равенство. Для объяснения этого требуется некоторая предыстория. В общем контексте вычислений хеш-функция принимает строку (или файл) любого размера и генерирует строку или целое число фиксированного размера, называемое хэш-кодом, обычно называемым только хеш-кодом. Некоторые часто используемые типы хэш-кода - это MD5, SHA-1 и CRC. Они используются в алгоритмах шифрования, индексировании баз данных, проверке целостности файлов и т. Д. Некоторые языки программирования, такие как Ruby, предоставляют тип коллекции, называемый хеш-таблицей. Хеш-таблицы - это словарные коллекции, в которых данные хранятся парами, состоящими из уникальных ключей и соответствующих им значений. Под капотом эти ключи хранятся как хэш-коды. Хеш-таблицы обычно называют просто хешами. Обратите внимание, как слово hash может относиться к хэш-коду или к хеш-таблице. В контексте программирования на Ruby слово «хеш» почти всегда относится к коллекции, подобной словарю.
Ruby предоставляет встроенный метод, называемый hash, для генерации хэш-кодов. В приведенном ниже примере он принимает строку и возвращает хэш-код. Обратите внимание, что строки с одним и тем же значением всегда имеют один и тот же хэш-код, даже если они являются разными объектами (с разными идентификаторами объектов).
"meditation".hash # Output: => 1396080688894079547
"meditation".hash # Output: => 1396080688894079547
"meditation".hash # Output: => 1396080688894079547
Метод хеширования реализован в модуле ядра, включенном в класс Object, который является корневым по умолчанию для всех объектов Ruby. Некоторые классы, такие как Symbol и Integer, используют реализацию по умолчанию, другие, например String и Hash, предоставляют свои собственные реализации.
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, когда мы храним что-то в хеш-коде (коллекции), объект, предоставленный в качестве ключа (например, строка или символ), преобразуется и сохраняется как хэш-код. Позже, при извлечении элемента из хэша (коллекции), мы предоставляем объект в качестве ключа, который преобразуется в хэш-код и сравнивается с существующими ключами. Если есть совпадение, возвращается значение соответствующего элемента. Сравнение выполняется с помощью команды 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
Оператор равенства регистра: ===
Многие встроенные классы Ruby, такие как String, Range и Regexp, предоставляют свои собственные реализации оператора ===, также известного как равенство регистра, тройное равенство или тройное равенство. Поскольку он реализован по-разному в каждом классе, он будет вести себя по-разному в зависимости от типа объекта, к которому он был вызван. Как правило, он возвращает истину, если объект справа «принадлежит» или «является членом» объекта слева. Например, его можно использовать для проверки того, является ли объект экземпляром класса (или одним из его подклассов).
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
Обратите внимание, что последний пример вернул false, потому что целые числа, такие как 2, являются экземплярами класса Fixnum, который является подклассом класса Integer. Знак ===, is_a? и instance_of? методы возвращают истину, если объект является экземпляром данного класса или любых подклассов. Метод instance_of более строгий и возвращает true только в том случае, если объект является экземпляром этого точного класса, а не подклассом.
Is_a? и kind_of? методы реализованы в модуле Kernel, который смешан с классом Object. Оба являются псевдонимами одного и того же метода. Проверим:
Kernel.instance_method (: kind_of?) == Kernel.instance_method (: is_a?) # Вывод: => true
Диапазон реализации ===
Когда оператор === вызывается для объекта диапазона, он возвращает истину, если значение справа попадает в диапазон слева.
(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
Помните, что оператор === вызывает метод === левого объекта. Итак, (1..4) === 3 эквивалентно (1..4). === 3. Другими словами, класс левого операнда будет определять, какая реализация метода === будет вызывается, поэтому позиции операндов не взаимозаменяемы.
Regexp Реализация ===
Возвращает истину, если строка справа соответствует регулярному выражению слева. / zen / === «Практикуйте дзадзэн сегодня» # Вывод: => true # то же самое, что «Практикуйте дзадзэн сегодня» = ~ / zen /
Неявное использование оператора === в операторах case / when
Этот оператор также используется под капотом в операторах case / when. Это его наиболее частое использование.
minutes = 15
case minutes
when 10..20
puts "match"
else
puts "no match"
end
# Output: match
В приведенном выше примере, если бы Ruby неявно использовал оператор двойного равенства (==), диапазон 10..20 не считался бы равным целому числу, например 15. Они совпадают, потому что оператор тройного равенства (===) равен неявно используется во всех операторах case / when. Код в приведенном выше примере эквивалентен:
if (10..20) === minutes
puts "match"
else
puts "no match"
end
Операторы сопоставления с образцом: = ~ и! ~
Операторы = ~ (равно-тильда) и! ~ (Удар-тильда) используются для сопоставления строк и символов с шаблонами регулярных выражений.
Реализация метода = ~ в классах String и Symbol ожидает регулярное выражение (экземпляр класса Regexp) в качестве аргумента.
"practice zazen" =~ /zen/ # Output: => 11
"practice zazen" =~ /discursive thought/ # Output: => nil
:zazen =~ /zen/ # Output: => 2
:zazen =~ /discursive thought/ # Output: => nil
Реализация в классе Regexp ожидает в качестве аргумента строку или символ.
/zen/ =~ "practice zazen" # Output: => 11
/zen/ =~ "discursive thought" # Output: => nil
Во всех реализациях, когда строка или символ соответствует шаблону Regexp, он возвращает целое число, которое является позицией (индексом) совпадения. Если совпадений нет, возвращается ноль. Помните, что в Ruby любое целочисленное значение является «истинным», а nil - «ложным», поэтому оператор = ~ можно использовать в операторах if и тернарных операторах.
puts "yes" if "zazen" =~ /zen/ # Output: => yes
"zazen" =~ /zen/?"yes":"no" # Output: => yes
Операторы сопоставления с образцом также полезны для написания более коротких операторов if. Пример:
if meditation_type == "zazen" || meditation_type == "shikantaza" || meditation_type == "kinhin"
true
end
Can be rewritten as:
if meditation_type =~ /^(zazen|shikantaza|kinhin)$/
true
end
Оператор! ~ Противоположен оператору = ~, он возвращает истину, если совпадения нет, и ложь, если совпадения есть.
Дополнительная информация доступна в этом сообщении в блоге.
person
BrunoF
schedule
29.05.2016
"a" == "a"
,"a" === "a"
и"a".eql? "a"
. Но это неверно:"a".equal? "a"
(у меня рубин 1.9.2-p180) - person PeterWong   schedule 23.08.2011a = Object.new; b = Object.new
, тогда все==
,===
,.equal?
,.eql?
вернутtrue
дляa
vsa
и false дляa
vsb
. - person Nemo157   schedule 23.08.2011