こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

Rubyの問題について質問です。

Rubyの資格試験の勉強をしています。
分からない部分がありまして質問させていただきます。
class Employee
attr_reader :id
attr_accessor :name
def initialize id , name
@id = id
@name = name
end
def to_s
return "#{@id}:#{@name}"
end
def <=> other
return self.id <=> other.id
end
employees = [ ]
employees <<Employee.new("3","Tanaka")
employees<<Employee.new("1","Suzuki")
employees<<Employee.new("2","Sato")
employee.sort!

(質問)
「return self.id <=> other.id」この部分のselfとotherが何をさしているのか分かりません。3つめでインスタント化している「employees<<Employee.new("2","Sato")」のは、selfに入りそれまでに入れた値はotherに入っているのでしょうか?

ご回答よろしくお願いします。

投稿日時 - 2014-02-11 22:27:57

QNo.8471410

困ってます

質問者が選んだベストアンサー

まず最初に間違いがありますので、それを修正しないと動きません。
employees = [ ]の上の行に
end
を追加する必要があります。そのままではエラーがでます。

また、最後の行は
employee.sort!
ではなく
employees.sort!
です。変数名が間違っていますので、これもエラーがでます。

デバッガを使えば質問の内容は簡単に確認できますので、それを使うのが理解する早道です。

それはそれとして、
>「return self.id <=> other.id」この部分のselfとotherが何をさしているのか分かりません。

def <=> otherがどのような形で呼ばれるかを考えればわかります。
このメソッドはsort!から呼ばれます。
return self.id <=> other.id
の行で最初に実行を止めたときのデバッガの出力を書いておきます。
(byebug) self
#<Employee:0x007fe12416ccb0 @id="3", @name="Tanaka">
(byebug) other
#<Employee:0x007fe12416c9b8 @id="1", @name="Suzuki">
この場合はsort!からは、はじめに、employees[0]<=>employees[1]の形で呼ばれています。
ここでは、def <=> otherが定義されていますので、
self.id <=> other.id
で比較されます。つまり "3" <=> "1"が実行されます。

>3つめでインスタント化している「employees<<Employee.new("2","Sato")」のは、selfに入りそれまでに入れた値はotherに入っているのでしょうか?

selfとotherのどちらになるかはsort!次第です。

余談ですが、
idが文字列になっていますので、文字列で比較されます。数値で比較したいのでしたら、
employees <<Employee.new(3,"Tanaka")
のようにidを数値にする必要があります。あるいは
return self.id.to_i <=> other.id.to_i
のように。

投稿日時 - 2014-02-11 23:21:33

お礼

とても分かりやすい説明ありがとうございました。

投稿日時 - 2014-02-12 07:49:03

ANo.3

このQ&Aは役に立ちましたか?

7人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

> 「return self.id <=> other.id」この部分のselfとotherが何をさしているのか分かりません。


下のプログラム3行目のtanakaがself, suzukiがotherです。
-----
tanaka = Employee.new(3,"Tanaka")
suzuki = Employee.new(1,"Suzuki")

p tanaka <=> suzuki # 結果は、1
p tanaka.<=>(suzuki) # これも同じこと
-----


employees << Employee.new("2","Sato")

employeesという配列(Array)にEmployee.new("2","Sato")という要素を追加しています。
employees.sort!で各要素間でself<=>otherの比較が行われて、その結果により順番の入れ替えを行って要素をid順にソートしています。

-----
employees.sort!
employees.each do |emp|
p emp
end
-----
-----結果(id順にソートされている---
#<Employee:0x1082acc @id=1, @name="Suzuki">
#<Employee:0x1082a90 @id=2, @name="Sato">
#<Employee:0x1082af4 @id=3, @name="Tanaka">
-----

投稿日時 - 2014-02-12 06:23:03

お礼

それぞれの動きが分かりやすかったです。ありがとうございます。

投稿日時 - 2014-02-12 07:52:09

ANo.2

んーと、これ最後の end は 2 つじゃないですか?
そうしないと Employee クラスの定義が終わりませんが……。

それはともかく、
def <=> other
return self.id <=> other.id
end
の self と other が何かという質問ですが、この部分は Employee クラスに対する <=> 演算子(別名 宇宙船演算子)の定義をしています。
http://www.minituku.net/courses/566428009/lessons/938940278/texts/873491413?locale=en
定義の内容は self の id メソッドの結果と other の id メソッドの結果に対して <=> を使った結果をそのまま Employee クラスに対する <=> 演算子の結果とする、というものになっています。

other については def の部分をこう書きかえて、<=> 演算子もメソッドの一種であることがわかればわかると思います。
def <=>(other)

では self は何かというと、これはクラスインスタンスメソッドの中で使うとそのメソッドが呼ばれているインスタンス自体を表します。

したがって、
> 3つめでインスタント化している「employees<<Employee.new("2","Sato")」のは、selfに入りそれまでに入れた値はotherに入っているのでしょうか?
は全く見当はずれな内容となっています。

投稿日時 - 2014-02-11 23:06:15

お礼

ミニツクのリンクありがとうございます。<=>宇宙船演算子というんですね。初めて知りました。

投稿日時 - 2014-02-12 07:51:03

ANo.1

違います。

<=> は明示的には呼び出されてませんが、sort! から呼び出されます。
sortについて調べてみてください。

投稿日時 - 2014-02-11 23:05:17

お礼

まさかsort!とセットになってるとは気づきませんでした。ありがとうございます。

投稿日時 - 2014-02-12 07:53:04

あなたにオススメの質問