その他の専門演習の先輩たちの話も聞こう。
これまでは雛型や骨組 -- ものの捉えかたについて考えた。 計算機のプログラムは、 同じようなことを繰り返し何度も行なう場合に役に立つ。 プログラムは「もしこれが自動化されたらどうなるか」 を常に考えて作っている。この講義では行なわないが、 画像をプログラムと連係させたりする場合、 何と何が連動するのかを頭に入れておく必要がある。
回数を指定して繰り返すとき:
繰り返す整数.times do
実行すること 繰り返す整数値分繰り返される
end
大きな数から始めて、徐々に小さな数にする場合:
始める整数.downto(終りにする整数) do |変数|
変数の処理
end
小さな数から始めて、徐々に大きな数にする場合:
始める整数.upto(終りにする整数) do |変数|
変数の処理
end
始める数と終る数が決まっている場合:
for 変数 始める整数 .. 終りにする整数
変数の処理
end
配列の要素を調べたり変更するには
配列で method を知っていると、例えば、
ランキングなどの結果をきちんと対応させるときにも応用が効く。
配列の要素を調べて、順序を変えたり、
または外から持ってきた配列を結合したりすることができる。
配列 momo とする。
momo = [3, 4, 1, 2]
これをいろいろ操作して method の復習をしたい。
irb コマンドの起動
irb コマンドを起動してみよう。
%irb
irb(main):001:0>
irb の終了は exit である。
と出る。簡単な振舞いを調べるのに、
irb 内で全て調べを済ませることができる。
テストモデルの設定
momo の配列をしまおう。
%irb
irb(main):001:0> momo = [3, 4, 1, 2]
=> [3, 4, 1, 2]
これで momo の配列を覚えた。
method を結合しよう
まずは前期で学んだ、
数字の若い順に並べ換える
sort を使おう。
irb(main):002:0> momo.sort
=> [1, 2, 3, 4]
と、きちんと並べかえることができた。
以降いくつかまとめてみる。
配列に配列を結合するには
+ を使うと、別の配列
komomo
を結合させることができる。
komomo = [6, 9, 8, 7, 0]
を定義しよう。
irb(main):003:0> komomo = [6, 9, 8, 7, 0]
=> [6, 9, 8, 7, 0]
komomo
も定義し終ったので、
momo+komomo
を実行しよう。
irb(main):004:0> momo + komomo
=> [3, 4, 1, 2, 6, 9, 8, 7, 0]
以降、
irb(main):開始行からの行数:0>
を除いて表示していくことにする。
ここで、
irb(main):005:0> momo
irb(main):006:0> komomo
の 2 つを実行し、これらの中身は変化していないことに注意しよう。
<< "要素"
とすると、もとの配列の最後の要素に新しい要素を付け加える。
momo
に
5 を付け加えてみよう。
irb(main):007:0> momo << 5
=> [3, 4, 1, 2, 5]
momo が変更を受けた。
irb(main):008:0> momo
で確認しよう。
もとの配列に複数の要素を付け加えるには
もとの配列に複数の要素を付け加えるには push("値1", "値2", ...)
を使う。また momo をもとの配列に定義し直して、5,9
を付け加えてみよう。
irb(main):009:0> momo = [3, 4, 1, 2]
=> [3, 4, 1, 2]
irb(main):010:0> momo.push(5, 9)
=> [3, 4, 1, 2, 5, 9]
また、文字列も一緒に扱うことができる。
irb(main):011:0> momo = [3, 4, 1, 2]
=> [3, 4, 1, 2]
irb(main):012:0> momo.push("mimi", "mumu")
=> [3, 4, 1, 2, "mimi", "mumu"]
である。
もとの配列に別の配列を付け加えるには
もとの配列の最後に別の配列を付け加えるには、
配列.concat(別の配列) とすればよい。
momo
に
komomo
を付け加えるには、
irb(main):013:0> momo = [3, 4, 1, 2]
=> [3, 4, 1, 2]
irb(main):014:0>komomo = [6, 9, 8, 7, 0]
=> [6, 9, 8, 7, 0]
irb(main):015:0> momo.concat(komomo)
=> [3, 4, 1, 2, 6, 9, 8, 7, 0]
となる。komomo は変わらず、
komomo = [6, 9, 8, 7, 0]
のままであることを確認せよ。
各要素 0 番目から最後まで 1 回ずつ使うには
each method を配列に使うことができた。
for 文では for i in 配列 -- 配列[i]の処理 -- end
が使えたが、ここでは each で確かめておこう。
例えば momo の要素を足して行く場合、
momo = [3, 4, 1, 2] ならば
sum = 0
momo.each{|j|
sum += j
}
momo の 要素にある情報をそれぞれ each 取り出してはsum に足してゆけ
とすればよい。sum の答えは 10 を得る。
irb で実行して調べてみよう。
%irb
irb(main):001:0> momo = [3, 4, 1, 2]
=> [3, 4, 1, 2]
irb(main):002:0> sum = 0
=> 0
irb(main):003:0> momo.each{|j|
irb(main):004:1* sum += j
irb(main):005:1>}
=> [3, 4, 1, 2]
irb(main):006:0> printf("%d\n",sum)
10
=> nil
逆順に配列するには
前期で学んだ reverse は逆順に並べるものであった。
momo = [3, 4, 1, 2] ならば reverse 後の配列 changed とすると
momo.reverse changed = [2, 1, 4, 3]
momo = [3, 4, 1, 2] のまま
である。
逆順に配列し直すには
reverse! は破壊的 method (配列を変更してしまう method)である。
! をつけると、
momo に method を作用させた結果を
上書き
してしまう。
> momo = [3, 4, 1, 2]
=> [3, 4, 1, 2]
> momo.reverse!
=> [2, 1, 4, 3]
> momo
=> [2, 1, 4, 3]
momo が変化してしまった。上書きするような method を破壊的 method と呼ぶ。
要素がどこにあるのか調べるには
index(値) とすると、値にあるかどうか 0 番目の要素から調べ、
一番初めに発見した場所(添字番号)を返す。
見つからない場合は nil を返す。
momo = [3, 4, 1, 2] ならば
> momo.index(3)
=> 0
> momo.index(1)
=> 2
> momo.index(0)
=> nil
である。要素は 0 番目から始まることを思い出そう。
3 という値のある位置は momo[0] である。
最後にある要素を取り出すには
合計点などを最後の配列にしまっておいた場合、それを取り出すには、
pop を使う。
> momo
=> [3, 4, 1, 2]
> momo.pop
=> 2
> momo
=> [3, 4, 1]
>
である。momo
の最後の要素を取り出してきたが、そのかわり
momo
は一つ配列が短くなった。要素がない場合は
nil
を返す。
1 から 4 までのカードを持ってきて、シャッフルして並べた場合を配列で考えよう。
右から順に開いて行くのを表すのは 変数
card
とすると、
card.rb
card = [3, 4, 1, 2] ならば
while i = card.pop
printf("取り出した数は %d です\n", i)
end
とつくる。
card.pop
により、数値は初めに 2、次に 1、その次に 4, 最後に 3
をとなる。計算が終ると
card = [nil]
となる。
最初にある要素を取り出すには
カードを左から順に取り出すときには shift が便利である。
これも、pop と同じように先頭要素を返したあと、配列を一つずつ縮めて行く。
> momo = [3, 4, 1, 2]
=> [3, 4, 1, 2]
> momo.pop
=> 2
> momo
=> [3, 4, 1]
である。繰り返していく場合には
card = [3, 4, 1, 2] ならば
while i = card.shift
printf("取り出した数は %d です\n", i)
end
で、初めに 3、次に 4、その次に 1、最後に 2 となる。計算が終ると
card = [nil]
となる。
重複した要素を除くには
uniq
で重複要素を取り除く。例えば
phone = [0, 2, 3, 4, 4, 1, 1, 1, 1, 1]ならば
changed = phone.uniq changed = [0, 2, 3, 4, 1]
phone は変わらず
phone.uniq! ならば phone = [0, 2, 3, 4, 1]
である。試してみよう。
> phone = [0, 2, 3, 4, 4, 1, 1, 1, 1, 1]
=> [0, 2, 3, 4, 4, 1, 1, 1, 1, 1]
> phone.uniq
=> [0, 2, 3, 4, 1]
> phone
=> [0, 2, 3, 4, 4, 1, 1, 1, 1, 1]
> phone.uniq!
=> [0, 2, 3, 4, 1]
> phone
=> [0, 2, 3, 4, 1]
! は破壊的 method を意味し、もとの定義を変更してしまう。
配列の数値を結合して文字列化するには
数値を計算した後に年月日にしたい場合などがある。
join("挟むのに使う文字")
を用いると便利である。
momo = [3, 4, 1, 2] ならば
momo.join("/") 文字列 "3/4/1/2" に変身
momo.join(", ") 文字列 "3, 4, 1, 2 " に変身
momo.join("$") 文字列 "3$4$1$2"に変身
momo.join 文字列 "3412" に変身
である。
細かく指定して並べ替えするには
比較して並び換えをする演算子を使って、
sort
をパワフルにすることができる。
<=>
比較して並び換えをする演算子
A <=> B
A が B よりも小さかったら (A < B)
A は B よりも先に決めておかなければならない
{A => B}
全て合わせて A <=> B
これを用いて、sort{|調べたいブロックあるいは要素,
並べ換えをするために作られるブロックあるいは要素 |
並べ換えをするために作られるブロックあるいは要素
<=>
調べたいブロックあるいは要素}
とすると、並びかえができる。
> momo = [3, 4, 1, 2]
> momo.sort{
* |momo,komomo|
* momo <=> komomo
>}
[1,2,3,4]
momo.sort{
|momo,komomo|
はじめにコピーされた komomo = [3, 4, 1, 2] が用意される
momo <=>
momo と komomo を比較し komomo では順番を入れ替えていく
} 得られる changed = [1, 2, 3, 4]
である。文字列が入っていても同じである。
momo = [lolo, toto, pepe , kiki] のとき
文字コード順では "k" < "l" < "p" < "t"
作ってみよう。
momo.sort{|momo,komomo| momo <=> komomo}
はじめにコピーされた
komomo = ["lala", "toto", "pepe", "kiki"]
が用意される。
momo とコピーされた komomo について比較し
komomo では順番を入れ替えていく
changed = ["kiki", "lala", "pepe", "toto"]
である。調べておこう。
> momo = ["lala", "toto", "pepe", "kiki"]
=> ["lala", "toto", "pepe", "kiki"]
> momo.sort{|momo,komomo| momo <=> komomo}
=> ["kiki", "lala", "pepe", "toto"]
予想通り、アルファベット順に並べかえることができた。
簡単なプログラムについて
プログラムとして作り直しておこう。
各成分を表示する方法を見てみよう。
each_component.rb
momo = ["lala", "toto", "pepe", "kiki"]
print("* * momo の要素 * *\n")
momo.each do |element| element は momo の要素を入れる変数
printf("%s \n", element)
end
print("* * momo の要素に bebe を追加 * *\n")
momo << "bebe"
momo.each do |element2| element2 は momo の要素を入れる変数
printf("%s \n", element2)
end
printf("今の要素数は %d \n", momo.length)
print("索引では \n")
result = momo.sort
while i = result.shift
printf("%s \n", i)
end
自分のプログラムの中で、起っていることがよく分らない場合、
動作の前後に上のように printf や p または
putsを使って調べるとよい。
配列の長さ(要素数)を返す
length(size でも同じ) を使うと、
配列の長さすなわち要素数がどれだけなのかがわかる。
momo
と
komomo
の配列の例では、
> momo = [3, 4, 1, 2]
=> [3, 4, 1, 2]
> komomo = [6, 9, 8, 7, 0]
=> [6, 9, 8, 7, 0]
> momo.length
=> 4
> komomo.length
=> 5
である。
先頭に要素を追加するには
先頭に要素を追加するには、
unshift(値) を使うとよい。
unshift で入った要素が 0 番目になり、
もとの配列要素は 1 つずつずれる。
>momo.usnhift(5)
=> [5, 3, 4, 1, 2]
である。
配列の負の要素
momo = [3, 4, 1, 2]
のとき、momo[-1] は最後尾、momo[-2] は最後尾から 2 番目を指す。
> momo = [3,4,1,2]
=> [3, 4, 1, 2]
> momo[-1]
=> 2
> momo[-2]
=> 1