【Ruby】sortとsort_byの違いをLeetCodeで学ぶ

LeetCodeの問題を解いていたんですが、sortメソッドとsort_byメソッドの違いがわからず解答に時間がかかったため、備忘録としてまとめます。

バージョンはRuby3.2です。

記事の信頼性

  • ぼくは独学で未経験から従業員300名以上の自社開発企業へ転職しました。
  • 実務ではVue.jsとRailsを毎日書いています。
  • 初心者や駆け出しエンジニアがつまづくポイントも身をもってよく理解しています。
目次

問題

LeetCodeの791. Custom Sort Stringという問題を解いており、次の解答を作成しました。

def custom_sort_string(order, s)
  order_hash = Hash.new(0)

  order.each_char.with_index do |char, i|
    order_hash[char] = i
  end

  s.chars.sort { |char| order_hash[char] }.join
end

しかしこれだと、下記のテストケースで失敗してしまいます。

入力値: order = "exv", s = "xwvee"
実際の出力結果: "weevx"
期待する出力結果: "eexvw"

そこで解答のsortメソッドの部分をsort_byに変更したところ、すべてのテストケースで成功しました。

しかし、sortsort_byの違いがわかっていないため、なぜこの変更でうまくいくようになったかが分かりませんでした、、。

解決方法

sortsort_byのちがいを理解することで、納得できました。

sort メソッドの挙動

sortメソッドは単に配列の要素同士を直接比較するだけです。

比較には<=>演算子(宇宙船演算子)が使われます。

<=>演算子は、二つの値を比較し、左辺が右辺より小さければ-1、等しければ0、大きければ1を返します。

numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
puts numbers.sort.inspect
#=> [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]

fruits = ["banana", "apple", "pear", "orange"]
puts fruits.sort.inspect
#=> ["apple", "banana", "orange", "pear"]

なおinspectメソッドは、オブジェクトを人間が読みやすい文字列形式で返します。

ここでは、配列の中身を見やすく表示するために使っています。

sort_by メソッドの挙動

sort_byメソッドは、ブロックを渡して使います。

ブロックの評価結果をキーとして、要素どうしを並び替えます。

# 文字列の長さで昇順にソート
fruits = ["banana", "apple", "pear", "orange"]
puts fruits.sort_by { |fruit| fruit.length }.inspect
#=> ["pear", "apple", "banana", "orange"]

# ハッシュのバリューでソート
fruits_hash = { "banana" => 5, "apple" => 3, "pear" => 4, "orange" => 6 }
puts fruits_hash.sort_by { |_, value| value }.inspect
#=> [["apple", 3], ["pear", 4], ["banana", 5], ["orange", 6]]

冒頭のLeetCodeの解答の場合、order_hash[char]の結果をキーにソートしたかったため、sort_byを使うべきでした。

def custom_sort_string(order, s)
  order_hash = Hash.new(0)

  order.each_char.with_index do |char, i|
    order_hash[char] = i
  end

  # sort ではなく sort_by を使う
  s.chars.sort_by { |char| order_hash[char] }.join
end

これで無事に問題を解くことができました!

おわりに

アルゴリズム系の問題をソートを使って解く場合は、sortsort_byをしっかり使い分けます。

  • 比較キーが単純な場合(数値や文字列の大小関係など)はsortを使う。
  • 比較キーが複雑な場合(別の値に基づいてソートするなど)はsort_byを使う。
参考文献
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

未経験でSESから従業員300名以上の自社開発企業に転職しました。業務や個人開発で直面した問題や、転職・学習の経験を発信していきます。

コメント

コメントする

目次