Rubyのsortとsort_byの違いを徹底比較!性能や安定ソートのコツを初心者向けに解説
生徒
「Rubyでバラバラな数字や名前を順番通りに並び替えたいときは、どうすればいいですか?」
先生
「それにはsortメソッドやsort_byメソッドを使います。データの量や並び替えの条件によって、どちらを使うかが重要になります。」
生徒
「二つの使い分けはどう判断すればいいんでしょう?効率の良い書き方があるなら知りたいです!」
先生
「処理の速さや、複数の条件で並び替えるコツがあります。初心者の方にも分かりやすく解説しますね!」
1. ソートとは?並び替えの基本を理解しよう
プログラミングの世界でソート(sort)とは、データを特定の規則に従って並び替えることを指します。例えば、バラバラな数字を小さい順(昇順)に並べたり、名簿を五十音順に整列させたりする作業のことです。パソコンのファイル一覧を日付順に並び替えるのも、内部ではこのソートという処理が行われています。
Rubyというプログラミング言語では、このソートを非常に簡単に実行するための命令が用意されています。初心者のうちは「ただ並べるだけ」と思いがちですが、データの量が多くなると、コンピュータがどれだけ効率よく(速く)処理できるかという性能の視点も大切になってきます。まずは、基本となるsortから見ていきましょう。
2. sortメソッドの基本的な使い方
sortは、配列の中身を単純に比較して並び替えるときに使います。数字であれば小さい順に、文字列であればアルファベット順や五十音順になります。特別な指定をしない場合、Rubyは自動的に「どっちが大きいかな?」と順番に比べて整列してくれます。
numbers = [40, 10, 30, 20]
sorted_numbers = numbers.sort
puts "並び替え前: #{numbers}"
puts "並び替え後: #{sorted_numbers}"
実行結果は以下のようになります。
並び替え前: [40, 10, 30, 20]
並び替え後: [10, 20, 30, 40]
このように、中身がシンプルな数字だけのときはsortを使うのが最も簡単です。なお、元の配列はそのままに、新しく並び替えた配列を作ってくれるのが特徴です。
3. sort_byメソッドは何が違うの?
sort_byは、「何に注目して並び替えるか」という基準を自由に決めたいときに使います。例えば、「単語そのものではなく、文字の長さで並び替えたい」といった場合に非常に便利です。また、性能の面でも大きな特徴があります。
words = ["リンゴ", "スイカ", "パイナップル", "ナシ"]
# 文字の長さ(length)を基準に並び替える
sorted_words = words.sort_by do |word|
word.length
end
puts sorted_words
実行結果は以下のようになります。
ナシ
リンゴ
スイカ
パイナップル
このように、データそのものではなく、データに付随する情報(この場合は文字数)を使って並び替えができるのがsort_byの強みです。
4. sortとsort_byの性能比較:どっちが速い?
ここが重要なポイントです。実は、多くの場合においてsort_byの方が動作が速いと言われています。なぜでしょうか?それは、比較の準備を一度だけで済ませる仕組みを持っているからです。
sortは、並び替えの途中で何度も「文字の長さは何かな?」と計算し直します。一方でsort_byは、最初に全てのデータの文字数を計算してメモしておき、そのメモを使って並び替えます。この「計算の回数を減らす」工夫により、特にデータの件数が多い時や、計算が複雑な時に劇的な速さの違いが生まれます。パソコンを操作していて動作が重いと感じるのは、こうした効率の悪い処理が原因のこともあります。Rubyを使うなら、基本的にはsort_byを使うのがおすすめの最適解です。
5. 多条件ソート:二つ以上の条件で並び替える
現実のデータ整理では、「まずは年齢順に、年齢が同じなら名前順に」といった、複数の条件(多条件ソート)が必要になることがあります。Rubyでは、配列の中に基準を二つ書くだけで、この複雑な並び替えを簡単に実現できます。
students = [
{ name: "田中", age: 20 },
{ name: "佐藤", age: 18 },
{ name: "鈴木", age: 20 },
{ name: "伊藤", age: 18 }
]
# まず年齢(age)で並べ、同じなら名前(name)で並べる
sorted_students = students.sort_by do |s|
[s[:age], s[:name]]
end
sorted_students.each do |s|
puts "#{s[:age]}歳: #{s[:name]}さん"
end
実行結果は以下のようになります。
18歳: 伊藤さん
18歳: 佐藤さん
20歳: 鈴木さん
20歳: 田中さん
このように[条件1, 条件2]と書くことで、優先順位をつけた並び替えが可能になります。これは名簿管理やランキング作成などで非常によく使われるテクニックです。
6. 安定ソートとは?並び順が崩れないコツ
プログラミングの用語に安定ソートという言葉があります。これは、「同じ値を持つデータがあったとき、並び替える前の順番が維持される」という性質のことです。以前のRubyでは不安定なこともありましたが、現在のRubyではsortもsort_byも「安定ソート」になっています。
例えば、最初に入力した「Aさん、Bさん」が同じ20歳だった場合、年齢順で並び替えても「Aさん、Bさん」の順番が入れ替わらないことが保証されています。これはデータを何度も加工する際に、意図しない順番の入れ替わりを防ぐためのとても大切な仕組みです。初心者のうちはあまり意識しなくても大丈夫ですが、「順番が守られる」という安心感を持って使いましょう。
7. 逆順に並び替えたいときはどうする?
「大きい順(降順)」に並び替えたいときもよくあります。そんな時は、並び替えた後にreverse(リバース)という「逆さまにする」命令を付け加えるのが一番簡単です。
scores = [80, 100, 50, 90]
# 小さい順に並べてから、逆にする
high_scores = scores.sort.reverse
puts "高得点順: #{high_scores}"
実行結果は以下のようになります。
高得点順: [100, 90, 80, 50]
他にも、sort_byの中で数字にマイナス(-)を付けることで逆順にするテクニックもありますが、まずはこのreverseを覚えるのが、読みやすさの点でもおすすめです。プログラムを「誰が見ても分かりやすく書く」ことは、上達への近道です。
8. エラーを避けるための注意点
ソートを使うときに初心者がやってしまいがちな失敗が、「違う種類のデータを混ぜてしまう」ことです。例えば、数字の10と、文字の"あ"を同じ箱(配列)に入れてソートしようとすると、コンピュータは「数字と文字、どっちが大きいの?」とパニックを起こしてエラーを出してしまいます。
パソコンを触り始めたばかりの方は、配列の中身が同じ種類(全部数字か、全部文字か)であることを確認する癖をつけましょう。もしエラーが出たときは、中身がバラバラになっていないかチェックしてみてください。一歩ずつ確認しながら進めば、必ず思い通りに動かせるようになりますよ。