Arrayオブジェクトは配列として扱われることが多いですが、Array#pushとArray#popを使うことで、「スタック」のように扱うこともできます。
[1] pry(main)> stack = [] => [] [2] pry(main)> stack.push("alice") => ["alice"] [3] pry(main)> stack.push("in") => ["alice", "in"] [4] pry(main)> stack.push("wonderland") => ["alice", "in", "wonderland"] [5] pry(main)> stack.pop => "wonderland" [6] pry(main)> stack => ["alice", "in"] [7] pry(main)> stack.pop => "in" [8] pry(main)> stack.pop => "alice" [9] pry(main)> stack => []
[1]で空のArrayオブジェクトを変数stackに代入し、[2][3][4]でArray#pushを使うことで次々に文字列オブジェクトをスタックに積んでいます。
この状態で[5]のようにArray#popを実行すると、stackの最後尾にある"wonderland"が返され、stackから"wonderland"が取り除かれたことが[6]で確認できます。
Arrayオブジェクトをスタックとして扱えるのと同様に、Array#shiftを使うことで、「(FIFO)キュー」のように扱えます。
[1] pry(main)> queue = [] => [] [2] pry(main)> queue.push("alice") => ["alice"] [3] pry(main)> queue.push("in") => ["alice", "in"] [4] pry(main)> queue.push("wonderland") => ["alice", "in", "wonderland"] [5] pry(main)> queue.shift => "alice" [6] pry(main)> queue => ["in", "wonderland"] [7] pry(main)> queue.shift => "in" [8] pry(main)> queue.shift => "wonderland" [9] pry(main)> queue => []
[1]で空のArrayオブジェクトを変数queueに代入し、[2][3][4]でArray#pushを使うことで次々に文字列オブジェクトをキューに詰めています。
この状態で[5]にようにArray#shiftを実行すると、queueの先頭にある"alice"が返され、queueから"alice"が取り除かれたことが[6]で確認できます。
Array#reverseやArray#reverse!を使うと、含まれているオブジェクトを逆順に並べたArrayオブジェクトを新たに生成します。Array#reverseは逆順にしたArrayをオブジェクトを返し、自身の順序は変更しません。対するArray#reverse!は、逆順にしたArrayオブジェクトを自分自身に代入します。
[1] pry(main)> array = [1, 2, 3] => [1, 2, 3] [2] pry(main)> array.reverse => [3, 2, 1] [3] pry(main)> array => [1, 2, 3] [4] pry(main)> array.reverse! => [3, 2, 1] [5] pry(main)> array => [3, 2, 1]
[1]では、配列リテラルを使って3つのオブジェクトを持つArrayをオブジェクトを生成、arrayに代入しています。[2]では、Array#reverseによってarrayを逆順に並び替えているため、[3, 2, 1]という配列が返ってきますが、arrayそのものに変更は加えないため、[3]のようにarrayは`[1, 2, 3]`のままです。Array#reverse!は、実行したオブジェクト自身を更新するため、[5]でarrayは`[3, 2, 1]`となっています。
Rubyの組み込みライブラリには、Array#reverseとArray#reverse!のような関係を持つメソッドがたくさんあります。ビックリマーク(エクスクラメーションマーク)の付いているメソッドは「破壊的メソッド」と呼ばれ、実行したオブジェクト自身の状態を変えるようなメソッドになっています。
これはあくまで慣例です。もちろん、破壊的でないメソッドにビックリマークを付けることもできますが、利用者にとって不便なだけです。もしあなたがライブラリを設計する場合は、利用者を困惑させないためにも、この慣例を守るようにしましょう。
Array#rotateを使うと、引数に指定したインデックスを先頭としたArrayオブジェクトを新たに生成できます。Array#rotate!はArray#rotateの破壊的メソッド版です。配列を「ずらす」と考えると分かりやすいでしょう。
[1] pry(main)> array = [1, 2, 3, 4, 5] => [1, 2, 3, 4, 5] [2] pry(main)> array.rotate(2) => [3, 4, 5, 1, 2] [3] pry(main)> array.rotate(-2) => [4, 5, 1, 2, 3]
[2]では、0から数えて2番目の要素、つまり3が先頭となるArrayオブジェクトが返されています。[3]のように、インデックスの指定には負の数を使うこともできます。
Array#sort_byを使うと、配列をソート(並び替え)できます。Array#sort_by!はArray#sort_byの破壊的メソッド版です。要素同士の比較には「<=>」演算子が用いられます。
[1] pry(main)> [1, 5, 3, 2, 0, -5].sort_by => [-5, 0, 1, 2, 3, 5]
Array#sortやArray#sort!といったメソッドも利用できますが、一般にArray#sort_byの方が高速です。
「<=>」は、その形状から「宇宙船演算子」と呼ばれる演算子で、「左辺 < 右辺」であれば-1を、「左辺 > 右辺」であれば1を、等しければ0を返す演算子です。宇宙船演算子は、整数や実数、以降の連載で紹介するTimeオブジェクトなど、さまざまなクラスのオブジェクトで利用できます。
[1] pry(main)> 1 <=> 2 => -1 [2] pry(main)> 2 <=> 1 => 1 [3] pry(main)> 1 <=> 1 => 0
余談ですが、この愛らしい形状とそのネーミングから、筆者の好きな演算子の一つです。
Array#shuffleを使うと、ランダムに並び替えたような配列を得ることができます。Array#shuffle!はArray#shuffleの破壊的メソッド版です。乱数を使って生成されるので、以下の実行結果は毎回変わります。
[1] pry(main)> array = ["queen", "of", "hearts"] => ["queen", "of", "hearts"] [2] pry(main)> array.shuffle => ["queen", "of", "hearts"] [3] pry(main)> array.shuffle => ["of", "queen", "hearts"] [4] pry(main)> array.shuffle => ["queen", "of", "hearts"]
Copyright © ITmedia, Inc. All Rights Reserved.