Ruby実用例 〜超簡単なデータ処理〜 のバックアップソース(No.10)

プログラムは,人がやるには苦痛を伴う単調な作業を正確に素早く行ってくれます.機械的に測定した実験データなどは,決まった処理を繰り返し行わなければならないことがあります.このような処理が,プログラムは大変得意です.

ここではRubyプログラムの便利さの一端を感じるため,「カンマで区切られた数値の,各行の平均値を取って出力する」という極簡単な処理を行ってみます.

* プログラムの名前 [#i293bd44]

名前は結構重要です.できれば何をするか分かる名前を付けましょう.ここでつくるプログラムは,各行の平均値をとるので「rowAverage.rb」という名前にしておきます.プログラムはコマンドラインで

 rowAverage.rb infile

とすれば実行できるようにします.「infile」というのは,入力データを含んだテキストファイル名を仮に表しています.実行時,実際のファイル名に置き換えてください.

* データの流れ [#z90239dc]

データ処理を行うので,まずどんなデータを入力して,どんなデータを出力するかをハッキリさせておきます.以下のような入出力を想定します.

** 入力データ [#w9fbe378]

 287.5 ,287.8 ,287.5 
 201.0 ,200.7 ,201.0 
 155.6 ,155.9 ,155.9,155.7
 135.1,134.7 ,134.7 
 124.5,124.2
 117.1 ,117.8 ,117.5 
 111.5 ,111.5 ,111.5 
 ...

何かの測定値がカンマで区切られています.区切りの量はいつも同じとは限りません.しかも,カンマの前後に半角スペースがあったりなかったりします.

** 出力データ [#p7e3c99c]

つぎのように,行の平均値のみを出力することにします.

 287.60
 200.90
 155.77
 134.83
 124.35
 117.47
 111.50
 ...


* コーディング [#p0f04cd2]

いくつかのステップに分けてプログラムを完成させて行きます.Rubyの慣習に倣い#=>という記述を付けています.#=>があった場合,その行を実行するとどんな値になるか,どのように表示されるかを#=>の後に示しています.以下の例ではほとんどwhile文中にあるので,最初の一回目の実行を示しています.

** ステップ1 [#i4ad32df]

まず,コマンドとして動作し,入力ファイルを各行ごとに取得するようにします.

 #!/usr/bin/env ruby
 
 while line = gets
   line.chomp!
   p line # => "287.5 ,287.8 ,287.5 "
 end

1行目はRubyスクリプトのコマンドとして動作させるための命令です.環境変数PATHの中から最初に見つかったrubyコマンドを実行するので,rubyのパスが「/usr/bin/ruby」の場合でも「/usr/local/bin/ruby」の場合でも対応できるので,便利な書き方です.

つづくwhile文で入力ファイルを行ごとに取得しています.getsは標準入力もしくは第一引数の内容を,文字列として一行ずつ得ることができます.ここではgetsの内容をlineに入れて,lineがnilになるまでwhileで繰り返しています.chomp!メソッドは,文字列末尾の改行文字を破壊的に削るものです.これは,思わぬ誤動作を防ぐためです.

上の書き方はRubyでフィルタ系のコマンドをつくる場合のイディオムのようなものですから,覚えておいて損はないでしょう.

** ステップ2 [#v8384dda]

各行をカンマで区切る,という動作を加えます.つぎのようにSTRING.split()メソッドを使います.

 #!/usr/bin/env ruby
 
 while line = gets
   line.chomp!
   p line.split(",") # => ["287.5 ", "287.8 ", "287.5 "]
 end

lineにsplit(",")メソッドを使用することで,lineの内容をカンマで区切ったものを要素とする配列になります.

** ステップ3 [#q1ba9feb]

余分な空白も取り除くようにします.

 #!/usr/bin/env ruby
 
 while line = gets
   line.chomp!
   p line.gsub(/\s/, "").split(",")
 end

** ステップ4 [#ya2fbf1d]

取り出した値

 #!/usr/bin/env ruby
 
 while line = gets
   line.chomp!
   line.gsub(/\s/, "").split(",").each{|x|
     p x
   }
 end


** ステップ5 [#uc3f538c]

 #!/usr/bin/env ruby
 
 while line = gets
   line.chomp!
   sum = 0.0; i = 0
   line.gsub(/\s/, "").split(",").each{|x|
     sum += x.to_f
     i += 1
   }
   printf("%.2f\r\n", sum/i)
 end
Valid XHTML 1.1! home >
トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS
Modified by 物理のかぎプロジェクト PukiWiki 1.4.5_1 Copyright © 2001-2005 PukiWiki Developers Team. License is GPL.
Based on "PukiWiki" 1.3 by yu-jiPowered by PHP 5.3.29HTML convert time to 0.003 sec.