2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

sortメソッドと<=>の解説

Posted at

##sortメソッド
sortとは、日本語で「並び替える」という意味です。つまり、sortメソッドとは、ある一定の基準で並び替えるメソッドです。
実際に具体例を見てみましょう

ary = [4, 2, 9, 8, 3, 16, 10]
p ary.sort
=> [2, 3, 4, 8, 9, 10, 16]

sortメソッドは、デフォルトで昇順に並び替えるメソッドです。上記の例では、配列の中身が昇順で並び変わっています。

降順で並び替えるには、2つの方法があります。
➀reverseメソッドを使う
➁<=>演算子を使う
順に説明していきましょう

##➀reverseメソッド
reverseとは「反転する」という意味です。つまり、reverseメソッドは、配列やハッシュなどの値を反転させるメソッドなんです。
実際にコードを書いてみると以下のようになります。

ary = [4, 2, 9, 8, 3, 16, 10]
p ary.sort.reverse
=> [16, 10, 9, 8, 4, 3, 2]

このように書けます。個人的にはメソッドを2個連続書けることに驚きました(今更なんですけどね笑)。同じクラスのメソッドは連続で書けるみたいですね。

##➁<=>演算子
宇宙船演算子ともいわれています。見た目が宇宙船に似ているからだそう。個人的にはあまり似ていないように見えますが笑
どんな使い方をするかというと、公式ドキュメントに書かれているのは

self <=> other は
・self が other より大きいなら正の整数
・self と other が等しいなら 0
・self が other より小さいなら負の整数
・self と other が比較できない場合は nil

実際に具体例を見てみましょう

2 <=> 1
=> 1
2 <=> 2
=> 0
2 <=> 3
=> -1
2 <=> 'hoge'
=> nil

上記の具体例をみると、公式ドキュメントに書いてあることが理解できるとおもいます。要は、

左辺が右辺よりも大きければ、1を返し、
左辺と右辺が同じでなら、 0 を返し、
左辺が右辺よりも小さければ、-1を返し、
比較できない場合は、nilを返す

それを理解したうえで、以下のようなコードを書くと降順になるんです。

ary = [4, 2, 9, 8, 3, 16, 10]
p ary.sort {|a, b| b <=> a}
=> [16, 10, 9, 8, 4, 3, 2]

僕はこの書き方を見て、{|a, b| b <=> a}をみて、「どんな処理をしてるんだろう?」って思ったので、どんな処理をしているのかを解説していきます。

##{|a, b| b <=> a}は何をしているのか?
これを考えるとき、比較するとよいのが下記のコードです。

ary = [4, 2, 9, 8, 3, 16, 10]
p ary.sort{|a, b| a <=> b}
=> [2, 3, 4, 8, 9, 10, 16]

ここで考えなければならないのが、各要素の「戻り値の合計」の変化によるものなんです。どんなものかを見ていきましょう
|a= 4, b=2|の時の戻り値
4 <=> 2
=> 1
|a= 4, b=9|の時の戻り値
4 <=> 9
=> -1
|a= 4, b=8|の時の戻り値
4 <=> 8
=> -1
|a= 4, b=3|の時の戻り値
4 <=> 3
=> 1
|a= 4, b=16|の時の戻り値
4 <=> 16
=> -1
|a= 4, b=10|の時の戻り値
4 <=> 10
=> -1

戻り値の合計は、1-1-1+1-1-1=-2

|a = 2, b=4|の時の戻り値
2 <=> 4
=> -1
|a = 2, b=9|の時の戻り値
2 <=> 9
=> -1
|a = 2, b=8|の時の戻り値
2 <=> 8
=> -1
|a = 2, b=3|の時の戻り値
2 <=> 3
=> -1
|a = 2, b=16|の時の戻り値
2 <=> 16
=> -1
|a = 2, b=10|の時の戻り値
2 <=> 10
=> -1

戻り値の合計は、-6
このように、a = 16までをやってみると、戻り値の合計が7個出てきます。

a=4のとき、戻り値の合計は、-1
a=2のとき、戻り値の合計は、-6
a=9のとき、戻り値の合計は、2
a=8のとき、戻り値の合計は、0
a=3のとき、戻り値の合計は、-4
a=16のとき、戻り値の合計は、6
a=10のとき、戻り値の合計は、5
この戻り値の合計を比較して、少ない順にみていくと、[2, 3, 4, 8, 9, 10, 16]と昇順になるんです。
つまり、

ary = [4, 2, 9, 8, 3, 16, 10]
p ary.sort{|a, b| a <=> b}
=> [2, 3, 4, 8, 9, 10, 16]

のようなブロックにすると昇順になるんです。理由が分かりましたね。
では逆に、

ary = [4, 2, 9, 8, 3, 16, 10]
p ary.sort{|a, b| b <=> a}

この場合はどうなるのでしょうか。
同じように計算すると、
a=4のとき、戻り値の合計は、1
a=2のとき、戻り値の合計は、6
a=9のとき、戻り値の合計は、-2
a=8のとき、戻り値の合計は、0
a=3のとき、戻り値の合計は、4
a=16のとき、戻り値の合計は、-6
a=10のとき、戻り値の合計は、-5
この戻り値の合計を比較して、少ない順にみていくと、[16, 10, 9, 8, 4, 3, 2]と降順になるんです。

まとめると、{|a, b| b <=> a}は何をしているのかというと、要素同士の比較をしているということです。

##実際に問題を解いてみましょう
image.png

提示されているプログラムは、ブロック内で降順になります。降順になる理由は、先ほど述べましたね。
そして、降順になった配列にreverseメソッドを適用することで昇順になるんです。

よって、今回の正解は、選択肢➁です

以上です。
何か間違いがございましたら、ご教示いただけますと幸いです。
【参考文献】

2
0
0

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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?