Rubyがミニツク

あなたのRubyの技術に関するより詳しい知識と理解を増やします。

Ruby入門コース

このコースについて

Rubyのeラーニング研修システムはRailsを使ってWebアプリケーション開発ができる技術者の育成を目指します。 そのため、Railsを扱うことができるだけのRubyの知識を得ることがRuby入門コースの目標となっています。

コンテンツ一覧

ヒント レッスンの名前をクリックすると、その内容を表示します。

次のコンテンツ ホームへ戻る

宇宙船演算子

<=>演算子は形が宇宙船に似ていることから宇宙船演算子と呼びます。この演算子も不等号と同じようにオブジェクトを比較するのに使います。左のオブジェクトが小さいと負の数を返し、どちらのオブジェクトも同じなら0を返し、左のオブジェクトが大きいと正の数を返します。

p 1 <=> 2  #=> -1
p 1 <=> 1  #=> 0
p 2 <=> 1  #=> 1

この条件を評価した結果をifで使った例が以下になります。

def comparing(args1, args2)
  result = args1 <=> args2
  if result == 1
    puts("左の値が大きい")
  end
  if result == -1
    puts("右の値が大きい")
  end
  if result == 0
    puts("値は同じ")
  end
end

sortメソッド

sortメソッドを使用した場合、配列の各要素を並べ替えた配列オブジェクトを返します。
並べ替え方はブロックで指定できます。ブロックを指定しない場合には、<=>演算子を使用して比較します。破壊的メソッドとして使用する場合には、sort!のように後ろへ「!」を加えます。

配列の各要素を並び換えるには、sortメソッドを使用します。sortメソッドをそのまま呼び出すと、各要素の参照先のオブジェクトが持っている<=>メソッドを使用して大小関係を判定し、並び換えを行った配列を返します。

ary = [100, 50, 5, 10, 1]
p ary.sort        #=> [1, 5, 10, 50, 100]

並び換えの条件を変更する場合は、比較方法をブロックで指定します。ブロックを指定していない時は<=>メソッドを使って比較しながら並び替えをしました。ブロックを指定した場合の並び替えは、2つの要素を比較している時に返ってくる評価値がどのような数なのかで判断しています。

0を渡された場合にはブロックパラメータを入れ換えません。正の数を渡すと、左のブロックパラメータが後の要素になり、右のブロックパラメータが先の要素になります。負の数を渡すと、左のブロックパラメータが先の要素になり、右のブロックパラメータが後の要素になります。

ary = [1, 5, 10, 50, "Ruby"]
p ary.sort{|x, y|
    if x == "Ruby"
      -1
    elsif y == "Ruby"
      +1
    else
       0
    end
  }        #=> ["Ruby", 1, 5, 10, 50]

上記のサンプルコードは配列オブジェクトの最後にある要素の"Ruby"を先頭に持ってきています。左のブロックパラメータに"Ruby"が入っていれば、先の要素にしたいので「-1」を返します。右のブロックパラメータに"Ruby"が入っていれば、同じく先の要素にしたいので「+1」を返します。他の要素を比較している時には、「0」を返してどちらの要素も入れ換えていません。

sortメソッドは元の配列オブジェクトの並びは変化しません。配列オブジェクト自身を並び換えるときはsortの後に「!」を付けて使用します。

ary = [100, 50, 5, 10, 1]
p ary.sort         #=> [1, 5, 10, 50, 100]
p ary              #=> [100, 50, 5, 10, 1]
p ary.sort!        #=> [1, 5, 10, 50, 100]
p ary              #=> [1, 5, 10, 50, 100]

sort!もブロックで並び換えの条件を指定できます。

ary = [1, 5, 10, 50, "Ruby"]
ary.sort!{|x, y|
  if x == "Ruby"
    -1
  elsif y == "Ruby"
    +1
  else
     0
  end
} 
p ary      #=> ["Ruby", 1, 5, 10, 50]

sort_byメソッド

sort_byメソッドを使用した場合、すべての要素についてブロック内で評価した結果に従って並び替えた配列オブジェクトを返します。破壊的なメソッドとして使用する場合には、sort_by!のように後ろへ「!」を加えます。

配列オブジェクトの要素を並び換えるのは、sortの他にもsort_byメソッドがあります。

ary = [1, 3, 5, 2, 4]
p ary.sort_by{|a| -a}    #=> [5, 4, 3, 2, 1]
p ary                    #=> [1, 3, 5, 2, 4]

各要素をブロックに呼出して評価した結果をもとに並び換えをおこないます。

ary = ["Ruby,012", "Rails,345", "HTML,067", "JavaScript,89", "Ada,346", "C,012"]
p ary.sort_by { |i|
    i_split = i.split(",")
    [i_split[1].to_i, i_split[0]]
  }
  #=> ["C,012", "Ruby,012", "HTML,067", "JavaScript,89", "Rails,345", "Ada,346"]
p ary
  #=> ["Ruby,012", "Rails,345", "HTML,067", "JavaScript,89", "Ada,346", "C,012"]

上記のサンプルコードでは、splitメソッドを使って「,」をもとに分割した要素を持つ配列オブジェクトを作成しています。作成された配列オブジェクトは、文字と数字の2つの要素に分かれています。<=>メソッドで配列オブジェクトを比較すると、最初に比較した要素が同じなら次の要素を比較して返す値を決めます。サンプルコードでは返り値に数字の要素を最初にして、文字の要素を後にした配列オブジェクトを返しています。最初に数字が同じ評価して、数字が同じなら文字を比較して並び換えているのです。

sort_byメソッドは元の配列オブジェクトの並びは変化しません。配列オブジェクト自身を並び換えるときはsort_byの後に「!」を付けて使用します。

ary = [1, 3, 5, 2, 4]
p ary.sort_by!{|a| -a}   #=> [5, 4, 3, 2, 1]
p ary                    #=> [5, 4, 3, 2, 1]

sortは要素どうしの比較をする際にブロックを実行して比較し、sort_byはまずブロックを評価した結果を集めて、評価結果の<=>メソッドを使うことにより並び換えをします。一般にsort_byの方が実行時間が短くなりますが、<=>メソッドが定義できない場合はsortを使うことになります。

each_with_indexメソッド

each_with_indexメソッドを使用した場合、配列内の要素1つずつとそのインデックスに対して特定の操作をおこないます。

ary = ["Ruby", "HTML", "JavaScript", "Rails"]
ary.each_with_index { |item, index| p item, index }

eachは各要素にブロック内の操作をするメソッドでした。このeach_with_indexメソッドも各要素にブロック内の操作をしますが、操作をする対象が各要素に加えてインデックスも操作できます。

injectメソッド

injectメソッドを使用した場合、配列の要素に対してブロックの実行結果を適用した結果を返します。最初に初期値と配列オブジェクトの最初の要素を引数に順次ブロックを実行します。

injectメソッドを使うと、2つの要素ごとにブロックの呼出しをおこないます。呼び出したブロックの最後の評価値を、次のブロックの呼出しの最初の要素に使います

ary = [1, 2, 3]
p ary.inject(10){|result, item| result + item}   #=> 16

injectメソッドの引数を最初の要素にして、配列オブジェクトの先頭の要素を次の要素にします。サンプルコードのブロックでは2つの要素を足した結果を、次のブロックの呼出しの最初の要素に持ってきます。ブロックパラメータは2つ必要なので、配列の要素から次の要素を呼び出します。このように順番に呼び出してブロックで評価するのがinjectメソッドになります。

初期値を省略した場合は、最初に配列オブジェクトの先頭の要素と2番目の要素が引数になります。

ary = [1, 2, 3]
p ary.inject{|result, item| result + item}       #=> 6

最後のブロックまで実行を終えたら、最後のブロックの実行結果を返します。


次のコンテンツ ホームへ戻る