↓↓クリックして頂けると励みになります。
【12 | Sort】 << 【ホーム】 >> 【14 | メソッドの利用】
メソッドとは、ある特定の一連の処理をまとめたプログラムの構造の1つです。
Rubyのメソッドは、オブジェクト指向プログラミング言語であるRubyにおいて、特定の処理や機能を実行するための手段です。
メソッドは、オブジェクトに対して呼び出され、そのオブジェクトの振る舞いを決定します。
Rubyのメソッドは、次のような特徴があります。
オブジェクトに関連付けられています:メソッドは、特定のオブジェクトに属しています。例えば、文字列オブジェクトのlengthメソッドは、その文字列の長さを返します。
再利用性が高い:メソッドは、同じ処理を何度も実行するために再利用できます。これにより、コードの繰り返しを避け、プログラムを効率的に保つことができます。
カプセル化されています:メソッドは、処理をカプセル化し、外部から隠蔽することができます。これにより、プログラムの部分的な修正が容易になり、コードの保守性が向上します。
Visual Studio Codeで以下のプログラムを作ってみましょう。
新規作成 【sort3.rb】
# sort3.rb def main(array) sort(array) for i in 0..(array.length-1) do puts (i+1).to_s + ':' + array[i].to_s end end def sort(array) for i in 0..(array.length-1) do maxN( array, i ) end end def maxN( array, n ) max = array[n] maxIndex = n for j in (n+1)..array.length do if ( array[j].to_i > max.to_i ) then max = array[j] maxIndex = j else max = array[n] maxIndex = n end array[maxIndex] = array[n] array[n] = max end end data = [10, 75, 24, 32, 98, 72, 88, 43, 60, 35, 54, 62, 2, 12, 82] main(data)
このプログラムでは、メソッドが三つあります。
一つめはsort()
、二つめはmaxN()
、もう一つはmain()
です。
メソッド名の後の括弧()
の中に引数を入れます。
引数はメソッドの呼び出しの時に入れる引数とイコールの関係を持っています。
ではプログラムを見ながら説明します。
mainメソッドの中に次の記述があると思います。
sort(array)
これがメソッドの呼び出しです。
このようにメソッドを呼び出すには、メソッド名とその括弧()
の中に与えたい引数を記述するだけで良いのです。
sort(array)
が処理されると、そのメソッドが処理されます。
def sort(array) for i in 0..(array.length-1) do maxN( array, i ) end end
このメソッドの中では、dataがarrayとなって処理されるのです。
このメソッドではすぐfor文でループすることになります。
ループするごとに今度はmaxNメソッドが呼び出されています。
引数はarrayと i です。
次にmaxNメソッドに処理が移り、一番大きな数字を探して前の方と入れ替える作業をします。
それらの作業を受けて、mainメソッドで出力する作業を行っています。
出力結果を確認してみましょう。
~/Desktop/Programming/RB $ ruby sort3.rb 1:98 2:88 3:82 4:75 5:72 6:62 7:60 8:54 9:43 10:35 11:32 12:24 13:12 14:10 15:2
Visual Studio Codeで以下のプログラムを作ってみましょう。
新規作成 【sort4.rb】
# sort4.rb def main( array ) sort( array ) for i in 0..(array.length-1) do puts (i+1).to_s + ':' + array[i].to_s end end def sort( array ) tmp=0 for i in 0..(array.length-1) do for j in 0..(array.length-(i+1)) do if (array[j].to_i < array[j+1].to_i) then tmp = array[j] array[j] = array[j+1] array[j+1] = tmp end end end end data =[10, 75, 24, 32, 98, 72, 88, 43, 60, 35, 54, 62, 2, 12, 82] main(data)
このプログラムは、「sort2.rb」をmainメソッドとsortメソッドに分けて書き直したプログラムです。
作業ごとにメソッドを分けるのは、プログラムが見やすくなるというメリットがあります。
出力結果です。
~/Desktop/Programming/RB $ ruby sort4.rb 1:98 2:88 3:82 4:75 5:72 6:62 7:60 8:54 9:43 10:35 11:32 12:24 13:12 14:10 15:2
Visual Studio Codeで以下のプログラムを作ってみましょう。
新規作成 【sort5.rb】
# sort5.rb def main( array, tmp0 ) sort( array, tmp0 ) for i in 0..array.length-1 do puts (i+1).to_s + ':' + array[i].to_s end end def sort( array, tmp0 ) sort2( array, 0, array.length-1, tmp0 ) end def sort2( array, min, max, tmp0 ) if ( (max - min) < 5 ) then sort3( array, min, max ) return end if ( tmp0.nil? ) then tmp0 = Array.new(array.length) end m = average( array, min, max ) largeCount=0 smallCount=0 for i in min..max do if ( array[i].to_f > m.to_f ) then tmp0[ min+largeCount ] = array[i] largeCount += 1 else tmp0[ max-smallCount ] = array[i] smallCount += 1 end end for i in min..max do array[i] = tmp0[i] end sort3( array, min, min+largeCount-1 ) sort3( array, max-smallCount+1, max-1 ) end def sort3( array, min, max ) for i in min..max-1 do for j in min..(max-(i-min)) do if ( array[j] < array[j+1] ) then tmp = array[j] array[j] = array[j+1] array[j+1] = tmp end end end end def average( array, min, max ) sum = 0.0 for i in min..max do sum += array[i] end return (sum/( max - min + 1)).to_f end data = [10, 75, 24, 32, 98, 72, 88, 43, 60, 35, 54, 62, 2, 12, 82] tmp = nil main(data, tmp)
tmp = nil
はこのあとtmp配列を使えるように定義しています。
作業領域用データを作成しています。
nilの意味は何もないという意味です。
まずmain( )
からsort()
に入ります。
sort()
では、sort2( array, 0, array.length-1, tmp0 )
という様にして引数を4つ与えているだけの処理を行っています。
これにより、 sort2()
に入ります。
ここで、min=0,max=14
に置き換わります。(今回のプログラムのみ。与えられるdataの数によって異なります。)
min=0,max=14
なので、最初はif( ( max - min ) < 5 )
の条件に当てはまらず、if ( tmp0.nil? )
が呼び出され、tmp0 = Array.new(array.length)
となります。
tmp0.nil?
は、tmp0がnilの場合tureを返します。
ここで、tmp0 = Array.new(array.length)
について説明します。
new演算子は新しくメモリーを確保するときに用います。
プログラムで配列や変数を扱うときには必ずメモリーを確保しなければなりません。
dataでは、直接配列に数字を代入しているので、自動的にメモリが確保されています。
しかしtmpではnilを代入していますから、この時点でメモリはまだ確保されていません。
自分でメモリを確保する必要があります。
配列のメモリの確保の仕方は次のように行います。
変数名 = Array.new(確保メモリ数)
次に、m = average( array, min, max )
より、average()
が呼び出され、i=0〜14
まで繰り返します。
データの平均が出てreturnします。
ここで、m = 平均値となります。
returnについて説明します。
averageの型がfloatになっているのに注目してください。
return文を使ってfloat型の戻り値を返しています。
今回の場合は、return (sum/( max - min + 1)).to_f
という記述がこの処理にあたります。
戻り値として(sum/( max - min + 1)).to_f
というfloat型の値を返しています。
次の記述を見てください。
if ( array[i].to_f > m.to_f ) then tmp0[ min+largeCount ] = array[i] largeCount += 1 else tmp0[ max-smallCount ] = array[i] smallCount += 1 end
これにより平均値より大きいものはtmp0[0]
から順に入っていき、小さいものはtmp0[14]
からtmp0[13],tmp0[12]・・
と入っていきます。
0〜14
まで調べると次に進みます。
for i in min..max do array[i] = tmp0[i] end
これにより配列tmp0の値が配列arrayに代入されます。
sort3( array, min, min+largeCount-1 )
によりmin=0,max=largeCount-1
(たぶん7)となりまた再びsort3( array, max-smallCount+1, max-1 )
に入ります。
同時にsort3( array, max-smallCount+1, max-1 )
によりmin=max-smallCount+1
(たぶん8)、max-1=14
となり sort3()
に入ります。
この時点で、2つのブロックに分けられました。
そして、この2つに分けられたブロックのそれぞれの平均値が出され、それよりも大きいもの、小さいものに分けられます。
この時点で4つのグループに分けられます。
そのとき、if ( (max - min) < 5 )
の条件に当てはまり、sort3()
に入って並び替えされます。
この並び替えの特徴は、ブロックで分けることによりsort3で処理される並び替えの動作が少なくなることにあります。
ちょっと複雑ですが、並び替えは今までのプログラムより早くできます。
出力結果です。
~/Desktop/Programming/RB $ ruby sort5.rb 1:98 2:88 3:82 4:75 5:72 6:62 7:60 8:54 9:43 10:35 11:32 12:24 13:12 14:10 15:2
Visual Studio Codeで以下のプログラムを作ってみましょう。
新規作成 【sort6.rb】
# sort6.rb def main( array, tmp0 ) sort( array, tmp0 ) for i in 0..array.length-1 do puts (i+1).to_s + ':' + array[i].to_s end end def sort( array, tmp0 ) sort2( array, 0, array.length-1, tmp0 ) end def sort2( array, min, max, tmp0 ) if ( (max - min).to_i < 5 ) then sort3( array, min, max ) return end if ( tmp0.nil? ) then tmp0 = Array.new(array.length) size = max - min + 1 half = size/2 + size%2 sort3( array, min, min+half-1 ) sort3( array, min+half, max ) counter1 = 0 counter2 = 0 for i in min..max do if ( counter1 > (half-1) ) then tmp0[i] = array[ min+half+counter2 ] counter2 += 1 elsif ( counter2.to_i > (max-min-half).to_i ) then tmp0[i] = array[ min+counter1 ] counter1 += 1 elsif ((array[min+counter1]).to_i > (array[ min+half+counter2]).to_i) then tmp0[i] = array[ min+counter1 ] counter1 += 1 else tmp0[i] = array[ min+half+counter2 ] counter2 += 1 end end end for i in min..max do array[i] = tmp0[i] end end def sort3( array, min, max ) for i in min..max-1 do for j in min..(max-(i-min)) do if ( array[j].to_i < array[j+1] .to_i) then tmp = array[j] array[j] = array[j+1] array[j+1] = tmp end end end end data = [10, 75, 24, 32, 98, 72, 88, 43, 60, 35, 54, 62, 2, 12, 82] tmp = nil main(data, tmp)
tmp = nil
で作業領域用データtmpを作ります。
まずmain()
からsort()
にはいります。
sort()
でsort2()
に入ります。
ここで、min=0,max=14
に置き換わります。
最初はtmp = nil
なのでif ( tmp0.nil? )がture
になります。
size=15,half=8
となり、sort3( array, min, min+half-1 )
でmin=0,max=7,sort( array, min+half, max )
でmin=8,max=14
となり、それぞれsort3()
に入ります。
sort3( array, min, min+half-1 )
では、min=0,max=7
なので、またmin=0,max=3
とmin=4,max=7
の2つに分けられます。
sort3( array, min+half, max )
では、min=8,max=14
なので、min=8,max=11
とmin=12,max=14
の2つに分けられます。
それぞれ再びsort3()
に入ります。
ここで、配列は次の4つの組に分けられています。
1組 10, 75, 24, 32
2組 98, 72, 88, 43
3組 60, 35, 54, 62
4組 2, 12, 82
return文 でループは終わります。
ここのreturn文は戻り値を返すためではなく、この処理を終わらせる意味を持っています。
このreturn文がないと、このメソッドの繰り返しループが永遠に繰り返されてしまい、最終的にはメモリを食い尽くしてしまう恐れがあります。
このreturn文があることで、sort3( array, min, min+half-1 )
とsort3( array, min+half, max )
のそれぞれの場所まで戻ります。
同じメソッドを繰り返して使うときは、最後の処理の時にreturn文をつけなければうまく動かなくなりますので気をつけてください。
ソートされた4組はループに入る前まで戻され、min=0,max=7
, とmin=8,max=14
の2組がそれぞれsort3()
にはいります。
出力結果です。
~/Desktop/Programming/RB $ ruby sort6.rb 1:98 2:88 3:82 4:75 5:72 6:62 7:60 8:54 9:43 10:35 11:32 12:24 13:12 14:10 15:2
【12 | Sort】 << 【ホーム】 >> 【14 | メソッドの利用】
↓↓クリックして頂けると励みになります。