inject methodを使うと簡単に書ける。injectの引数は変数resultの初期値を指定し、iには配列の要素が入る。
sum=bar.inject(0){|result,i| result+i*i}
inject methodを使うと簡単に書ける。injectの引数は変数resultの初期値を指定し、iには配列の要素が入る。
sum=bar.inject(0){|result,i| result+i*i}
Rubyでは基本的に配列は一次元。多次元配列を定義する方法はいつくかあるようだが、その中の一つ。
da=Array.new(3).map!{Array.new}
配列の初期化ついては注意が必要。
da=Array.new(3,Array.new(4,0))
のようにnewの引数に初期値を与えると、3個の配列がすべて同じオブジェクトになってしまう。
da[0][1]=7 p da #=> [[0,7,0,0],[0,7,0,0],[0,7,0,0]]
da=Array.new(3).map!{Array.new(4){0}}
のようにブロックを使用すれば大丈夫。
*確認したところ、
da=Array.new(3).map!{Array.new(4,0)}
でも問題なかったが、ブロック文の方が安全か。
一次元配列でさらに確認してみると、
ary=Array.new(3,"foo") ary[0].capitalize! p ary #=>gt;["Foo", "Foo", "Foo"]
とすべての要素が化けてしまうが、最後が破壊的メソッドでなく
ary[0]=ary[0].capitalize
のように代入してしえば一つの要素だけを変更できる。
とりあえず、配列の取扱いは代入を基本としている限りは大丈夫そうだが
念のためブロックを使って初期化するに越したことはない。
元素記号は一文字のもの(H,Oなど)と二文字(Ptとか)のものがあるため、固定長レコードで処理しようとすると2バイト分確保しておく必要がある。そうすると、一文字のものについてはunpackしたときに余分な空白がついてしまう。strip methodで空白を落とせるが、少し煩雑な気がしなくもない。
buf = rec.unpack("a2") printf("%3s\n",buf[0].strip)
open methodの第2変数にbを追加すると、”バイナリモード(ここでの「バイナリ」は改行方式を指すのみであって、取り扱うデータ自体がバイナリかそうでないかは特に関係がない)”で書き込みが行われる。
bin = open("test.bin", "wb")
pack methodで配列中のデータを変換する。下は、配列barの中身を2バイトの文字列と8バイトの倍精度実数x3、計26バイトの固定長に変換する。4バイトの単精度実数にしたい場合は、d→fと変更すればよい。
bin.print(bar.pack("a2d3"))
生成したファイルの容量が、きっかり26バイトになっているのにはちょっと感動。Fortranだと、単にwrite, readするだけでデータ長はほとんど意識しないので。読み取りにはunpackメソッドを用いる。
bin = open("test.bin", "rb") while rec = bin.read(26) buf = rec.unpack("a2d3") end
さらに、seek methodでデータ読み取り(書き込みも)の開始位置を指定できる。
一行のデータがrecバイトのとき、
bin.seek(n*rec)
でn行読み飛ばし、
bin.read(rec)
でn+1行目から読んでいくことができる。これは便利。