プログラミング言語論 第8回 11/24

Programing Language

はじめに

前回おさらい
  1. 配列(Arrayクラス)を扱う方法を学んだ
  2. このArrayに対する処理を通じて、Rubyでプログラミングの基本的な考え方にも触れた
ブロック
文法的確認

Ruby, Scala, Lisp などの言語では(明示的な指示がなければ)ブロック内に並んだいくつかの式の中で最後の式(ブロック内に含まれる式が1つならば必然的にその式)の値がブロックや関数の値として採用される(そのため return文は使われないことが多い)。

資料の提示と、windows操作について(補足)
今日の狙い
Stream

4 配列を扱う(つづき)

4.9 変形 フィルター 畳み込み

配列要素に対して繰り返すメソッドは 以下のようなものがある (実はもっといろんなバリエーションがあるが ここではその中で根源的なものを4つ紹介する)。map

each for による記法と同等の動作
もとの配列を値として返すので ブロックの中で
何かの作用を起こすという使い方をする
map 新しい配列を生成して返す
新しい配列の各要素の値は もとの配列の各要素に ブロックを適用した結果
select 条件を満たすものだけを選択して 新しい配列を作る
reduce 集約値を得る
引数の数
コーディングの方針

注)従来の手続き型言語では

n=a.size
i=0
while i < n do
      puts a[i]
      i+=1
end

のような記法もあるが、本科目ではこういう書き方はなるべく避け、 関数とメソッドの呼び出しを活用してコンパクトに書くことをめざす

mapの例

各メソッドの解説(変形 選択 畳み込み)

1. map ブロック

各要素にメソッドを適用し、新たな配列を生成 (右図2は前回の例題のデータの流れ)

a.map{|e|e*3}

補注) Enumerable

2. .select ブロック (等)

条件を満たす要素だけを選んで配列を生成 優先度

a.select{|e|e%3==0}

演算子1 演算子2

補足:

3. .reduce + ブロック (ブロックは2引数)

(または .inject(言語によっては foldとも呼ぶ)) 2引数 集約値を得る

3’. .reduce シンボル
a.reduce(:+)
a.reduce(0,:+)
階乗2
reduceの3つのパターン
3’’. reduce についての補足と考察

4 練習課題

設問1から100までの数を4乗した数の列の中で、 (どこかの桁に)6という文字を含むものだけを選び出す

例:

1**4 -> 4 ×
2**4 -> 16
3**4 -> 81 ×
4**4 -> 256
5**4 -> 625

=> 16, 256, 625, …

解いてみる

この節には、順を追って プログラム例が示されているが、なるべくここを見る前に 自分で解いて見ること

宿題
いくつかの入力例 12

‐‐‐ (以下はあとで見て下さい)

1 4乗の数値列(Array)を生成する
1..100
(1..100).to_a
(1..100).to_a.map{|n|n**4}
(1..100).map{|n|n**4}       # これでもいい
[*1..100]     # ややマニアックな書き方(慣れると心地いい)
to_s
2 6という文字を含むかどうか調べる
1296.to_s       # 数値を文字列に変換する
1296.to_s.include?('6') # ある文字列を含むかどうか
3 条件を満たすものを選ぶ
(1..100).map{|n|n**4}.select{|nn|nn.to_s.include?('6')}
# もしくは もとの数を配列にする
(1..100).select{|n|(n**4).to_s.include? '6'}
4 もとの数と4乗した結果を示すような表記にする
(1..100).select{|n|(n**4).to_s.include? '6'}.
    map{|n|"#{n}**4 => #{n**4}"}
5 全体をつないで1つの文字列にする
(1..100).select{|n|(n**4).to_s.include? '6'}.
    map{|n|"#{n}**4 => #{n**4}"}.
    join(', ')

4.11 配列のおさらい

本節は、各自で(マニュアルを参照しつつ) 試してみて下さい。

知っておくと便利なメソッド

(既出のものも含む)arrayのメソッド

.join つなぐ(これは既出) a * ‘,’ という記法もある
.size or.length 長さ ( 〃   )
.dup # DUPlicate = 複製する
# 破壊的メソッド(配列に変更を加えるメソッド)を使う時は
# 予めdupしておくのがいい
Enumerable#first <-> Enumerable#.last
Enumerable#drop <-> Enumerable#take
Array#sample
Enumerable#sort Enumerable#sort_by
Enumerable#zip (ary1, ary2,…) # zipper とか zip loc の zipです
zip

その他のメソッド

探す

    .index .find .find_all

変形

    .reverse .rotate .shuffle

大きなものを生成してしまうもの

(数学で昔ならった順列と組合わせに関連する)

    .permutation .repeated_permutation     .combination .repeated_combination     .product .cycle

順列と組合わせ

  # 注) 出発点となる配列のサイズが大きくなると、生成される配列が   # 爆発的に大きくなる(場合によってはPCが止まってしまう)ので注意

組み換え

    Enumerable#each_cons     Enumerable#each_slice     Enumerable#partition

基本技術のまとめ

参照 添字を1つ指定
始点添字と数を指定
代入(!) 添字を1つ指定
始点添字と数を指定 伸び縮みする
範囲を指定
抜出し(!) 先頭 末尾 位置指定
.shift .pop .delete_at
値を使うことが多い
追加(!) 先頭 末尾 位置指定
.unshift .push (または «) .insert

配列を使う練習(復習)課題

  1. 1~100からなる配列

  2. (1.の配列について)各要素を3倍する

  3. (1.の配列について)3の倍数だけを選び出す

  4. a’ ~ ’z’までの文字列からなるサイズ26の配列

  5. [1, 2, 3, 1, 2, 3, …] と繰り返す サイズ20の配列

  6. 乱数からなる配列を作る 補足:

    rand => 0 以上 1 未満の実数を返す
    rand(n) => 0 以上 n 未満の整数を返す
    rand(6)+1 => 1から6の間の値をランダムに(サイコロの働き)
  7. 最大のものを見つける 最大のものを見つける   (a.max と書けるのだが今日はreduceを練習して下さい)

    注) 式0 ? 式1 : 式2 は if式と同じ意味の
       3項演算子的な表現(CやJavaにもあるのと同じ)。
       ただし ? の前にスペースが必要。
       これは rubyでは ? も名標(変数名など)に使える文字だから
発展課題

「最大のものを見つける」ことができたら、次に、 「最大のものは何番目にあったか」を求めてみて下さい。