1. Qiita
  2. 投稿
  3. Ruby

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

  • 20
    いいね
  • 3
    コメント

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: 外部資料