はじめに
controllerで、orderメソッドを使うことは皆さんも多いと思うが、orderメソッドはデータベース内の値を基準に並び替える際に役に立つが、データベース内の値以外で、並び替えを行いたい時には使えない。
そこで出てくるのがこのsortメソッド
ここでは、sortメソッドの使い方を簡単に記述していく。
配列をsort
a = [2,3,1,4,5,1]
p a.sort
# => [1, 1, 2, 3, 4, 5]
デフォルトは昇順
降順にしたい時は、reverseメソッドを使う。
reverseメソッド
a = [2,3,1,4,5,1]
p a.sort.reverse
# => [5, 4, 3, 2, 1, 1]
もっと拡張性の高い並び替えをしたい時は、sort_byメソッドを使用する。
sort_byメソッド
s = ["aaaaa","b","cc"]
p s.sort_by {|array| array.size}
# => ["b", "cc", "aaaaa"]
この場合、文字の数で並び替えしている。
ハッシュをキーでsortする
ハッシュに対してsortメソッドを使いたい時も基本的には同じだ。
ハッシュをキーで昇順sortする
h = { "def" => 2, "ghi" => 1, "abc" => 3 }
p h.sort
p h
# => [["abc", 3], ["def", 2], ["ghi", 1]]
# => {"def"=>2, "ghi"=>1, "abc"=>3}
以上より、ハッシュのsortメソッドでは、
ハッシュのキーの昇順でソートできることが分かる。
ハッシュの値(バリュー)の昇順ではないのだ。
ここで注意しなければならないのが、
ハッシュでsortを使う場合、戻り値は2次元の配列(詳しくは、Enumerableモジュール)になるということ。
to_hメソッドで配列からハッシュへ
h = { "def" => 2, "ghi" => 1, "abc" => 3 }
p h.sort.to_h
# => {"abc"=>3, "def"=>2, "ghi"=>1}
ハッシュをキーで降順sortする
これも同じで、reverseメソッドを用いるだけだ。
ハッシュを値(バリュー)でsortする
ハッシュを値で昇順sortする
ハッシュの値による昇順ソートを行うには、下記の2つの方法がある。
- ハッシュのsort_byメソッドにブロックを渡し、sort基準をカスタマイズする
- ハッシュのsortメソッドにブロックを渡し、sort基準をカスタマイズする
ハッシュのsort_byメソッドによる値(バリュー)の昇順ソート
h = { "def" => 2, "ghi" => 1, "abc" => 3 }
p h.sort_by{ | key, value | value }
p h
# => [["ghi", 1], ["def", 2], ["abc", 3]]
# => {"def"=>2, "ghi"=>1, "abc"=>3}
ハッシュのsort_byメソッドにブロックを引数として渡した場合、ブロック変数にキーと値(バリュー)の2つが渡される。
そして、ブロックの戻値として値を返すと、その値を基準にソートされる。
値を基準にソートすることは、ハッシュの値同士を比較して昇順に並び替えすることになり、
値が小さいなら先に、値が大きいなら後に並び替えられる。
結果、昇順に並び替えられる。
またここでは、sort_byメソッドを使用したレシーバのハッシュ自体はソートされないことも確認できた。
ハッシュのsortメソッドによる値の昇順ソート
sortメソッドにブロックを引数として渡すと、ブロック変数にsort用に比較する対象のハッシュの要素が2つ渡される。
この2つの要素は [ key, value ] の配列。
2つの要素を比較するには、一般的に <=> 演算子が用いられる。
例えば、ブロック変数を | a, b | とすると、並び替え用に演算子を a <=> b として用いた場合、aがbより小さい時はaが先に、aがbより大きい時はaが後に並び替えられる。
これを利用し、ハッシュの値の昇順ソートを行うには、a[1] <=> b[1] という比較結果をブロックの戻値にする。
h = { "def" => 2, "ghi" => 1, "abc" => 3 }
p h.sort{ | a, b | a[1] <=> b[1] }
p h
# => [["ghi", 1], ["def", 2], ["abc", 3]]
# => {"def"=>2, "ghi"=>1, "abc"=>3}
ブロック変数a、bは、[ key, value] の配列だったので、a[1]、b[1]共にハッシュの値であることに注意する。
ハッシュを値で降順sortする
ハッシュの値(バリュー)で降順ソートを行う時、sort_byメソッドを使用する場合は、昇順ソートをした後にreverseメソッドを使う、という流れは今までと同じだ。
sortメソッドを使用する場合は、reverseメソッドを使うのではなく、
ハッシュのsortメソッドにブロックを渡し、sort基準をカスタマイズしなければならない。
ハッシュのsortメソッドによる値の降順ソート
降順でソートするには、ブロック変数を| a, b | とすると、並び替え用に <=> 演算子を b <=> a として用いた場合、aがbより小さい時はaが後に、aがbより大きい時はaが先に並び替えられる。
h = { "def" => 2, "ghi" => 1, "abc" => 3, "ddd" => 5 }
p h.sort{ | a, b | b[1] <=> a[1] }
# => [["ddd", 5], ["abc", 3], ["def", 2], ["ghi", 1]]
ハッシュのsort結果をto_hでハッシュにする
これまでソートしてきた記述をまとめると、、
h = { "def" => 2, "ghi" => 1, "abc" => 3 }
p h.sort.to_h
p h.sort.reverse.to_h
p h.sort_by{ | k, v | v }.to_h
p h.sort{ | a, b | b[1] <=> a[1] }.to_h
p h
# => {"abc"=>3, "def"=>2, "ghi"=>1}
# => {"ghi"=>1, "def"=>2, "abc"=>3}
# => {"ghi"=>1, "def"=>2, "abc"=>3}
# => {"abc"=>3, "def"=>2, "ghi"=>1}
# => {"def"=>2, "ghi"=>1, "abc"=>3}
おわりに
並び替えのメソッドは他にも存在しているらしいが、今回はrubyで一番ベーシックな並び替えメソッドを紹介した。とはいえ、この記事は下の参考記事のほぼコピペだ。少しずつ、自分の言葉でもアウトプットできるようにこれからも精進していきたい。
参考記事