ブロックなしで呼び出されたArray#sort (およびsort!
) は との比較を行う<=>
ため、ブロックは冗長です。これらはすべて同じことを達成します:
books.sort!
books.sort_by!{|x| x}
books.sort!{|firstBook, secondBook| firstBook <=> secondBook}
デフォルトの動作をオーバーライドしていないため、2 番目と 3 番目の形式は不必要に複雑です。
では、これはどのように機能するのでしょうか?
最初の形式は、何らかのソート アルゴリズムを使用して配列をソートします。どちらが先かは関係ありません。2 つの要素を比較して、どちらが先かを判断できる必要があります。(これについては以下で詳しく説明します。)自動的に、舞台裏で、上記の 3 行目と同じロジックに従います。
中間のフォームでは、何を並べ替えるかを選択できます。例: 各項目について、その項目 (デフォルト) で並べ替えるだけでなく、その項目の長さで並べ替えることができます。
books.sort_by!{|title| title.length}
次にbooks
、短いタイトルから長いタイトルの順に並べ替えられます。各項目でメソッドを呼び出すだけの場合は、別のショートカットを使用できます。これは同じことを行います:
books.sort_by!(&:length)
最終的な形式では、比較自体を制御できます。たとえば、後方に並べ替えることができます。
books.sort!{|first, second| second <=> first}
ブロックに2 つのsort
項目を渡す必要があるのはなぜですか? また、それらは何を表しているのですか?
Array#sort
(およびsort!
)ブロックを使用すると、ソートの比較ステップをオーバーライドする方法です。どのような順序で並べるかを判断するために、並べ替え中のある時点で比較を行う必要があります。ほとんどの場合、比較を上書きする必要はありませんが、上書きする場合は、これが可能なフォームであるため、ブロックに渡される 2 つの項目が必要です。この 2 つの項目は、今すぐ比較する必要があります。実際の例を見てみましょう。
[4, 3, 2, 1].sort{|x, y| puts "#{x}, #{y}"; x <=> y}
これは以下を出力します:
4、2
2、1
3、2
3、4
これは、この場合、配列をソートするために、and 、次にand 、次にand 、最後にandをsort
比較したことを示しています。正確な詳細は、この議論には関係なく、使用されているソート アルゴリズムに依存しますが、すべてのソート アルゴリズムは、ソートするために項目を比較できる必要があります。4
2
2
1
3
2
3
4