LoginSignup
95
68

More than 5 years have passed since last update.

Ruby の文字列比較 [eql?, equal?, ==, ===] の使い分けを汗臭く説明 #ruby

Last updated at Posted at 2015-01-15

Ruby の文字列比較 [eql?, equal?, ==, ===] の使い分けを:sweat_drops::sweat_drops:汗臭く:sweat_drops::sweat_drops:説明します

:musical_score: 概要

Ruby の文字列比較 [eql?, equal?, ==, ===] の使い分け ( :see_no_evil::hear_no_evil::speak_no_evil: ) について

:rage::feelsgood::rage::feelsgood::rage::feelsgood:
:feelsgood::sweat_drops::sweat::disappointed_relieved::cold_sweat::rage:
:rage::sweat::disappointed_relieved::cold_sweat::sweat_drops::feelsgood:
:feelsgood::disappointed_relieved::cold_sweat::sweat_drops::sweat::rage:
:rage::cold_sweat::sweat_drops::sweat::disappointed_relieved::feelsgood:
:rage::feelsgood::rage::feelsgood::rage::feelsgood:

汗臭い成分はここまで。

:raised_hand: 内容を読む前に

又その話かよ :rage1: と思ったあなた。
はい、その話です。

すでに理解している方は特に読む意味がない記事です。
自分が未だに、この部分を覚えていなくて

:worried::question:「 あれ? eql? と equal? ってどっちがどっちだっけ?」

と、都度検索しているので、
1 回自分でまとめ直したいと思いました。

同値性

Images

:neckbeard::id:1 :o: :neckbeard::id:2
:neckbeard::id:1 :o: :neckbeard::id:1
:neckbeard::id:1 :x: :smiley::id:3

eql?

String#eql? は、同値性の比較を行う。
文字列の内容が等しければ別のオブジェクトでも true を返却する。

hoge = 'hoge'
puts hoge.eql?(hoge) # => true
puts hoge.eql?('hoge') # => true

Hash のクラス内での比較に使われる。

hash = {}
hash[hoge] = 'test'
puts hash[hoge] # => test
puts hash['hoge'] # => test

==

String#==(other)String#eql? と同様に同値性の比較を行う。
ただし、 other が String 以外だった場合、

  • other#to_str があれば、 other == self で比較
  • それ以外は false を返却

する点が異なる。

hoge = 'hoge'
puts hoge == (hoge) # => true
puts hoge == ('hoge') # => true

hash = {}
hash[hoge] = 'test'
puts hash[hoge] # => test
puts hash['hoge'] # => test

class Age
  def initialize(age)
    @age = age
  end

  def to_str
    @age.to_s
  end

  def ==(other)
    self.to_str == other
  end
end

puts '20'.eql?(Age.new(20)) # => false
puts '20' == Age.new(20) # => true

===

String#===(other) の機能面は String#==(other) と同じ。

用途の違いがあり、
String#===(other) は case 文で暗黙的に使用されている。

def test
  %w(hoge hige hage hoo).each do |text|
    ret = case text
    when 'hoge' then 'ほげ'
    when 'hige' then 'ひげ'
    when 'hage' then 'はげ'
    else text
    end
    puts ret
  end
end

test

class String
  # override して、呼びだされていることを確認
  def ===(other)
    puts "**#{other}**"
  end
end

test
  • 出力
ほげ
ひげ
はげ
hoo
**hoge**
**hoge**
**hoge**
hoge
**hige**
**hige**
**hige**
hige
**hage**
**hage**
**hage**
hage
**hoo**
**hoo**
**hoo**
hoo

同一性

Images

:neckbeard::id:1 :x: :neckbeard::id:2
:neckbeard::id:1 :o: :neckbeard::id:1
:neckbeard::id:1 :x: :smiley::id:3

equal?

内部的には Object#equal? が呼び出されています。

Object#equal? は同一性をチェックします。
内部的には Object#object_id を比較しています。
同じ文字列でも、同一のオブジェクトでなければ false になります。

hoge1 = 'hoge'
hoge2 = 'hoge'

puts hoge1.object_id # => 12887137880
puts hoge2.object_id # => 12887137860

puts hoge1.equal?(hoge2) # => false
puts hoge1.equal?(hoge1) # => true

使い分け表

Method 同値性 同一性 他オブジェクトの比較 case 文
eql? :o: :x: :x: :x:
== :o: :x: :o: :x:
=== :o: :x: :o: :o:
equal? :x: :o: :x: :x:

:books: 外部資料

95
68
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
95
68