DATA変数と__END__トークンがテストに便利
今回は、ちょっとしたRubyプログラムのテストに便利なDATA変数の使い方のメモです。
DATA変数とは
Rubyプログラムファイルに__END__トークンだけの行が含まれている場合、その次の行以降にアクセスする為のストリームとしてDATA変数が定義されます。
この機能を使うと、paizaやCodeIQの課題なんかでよくある複数行の標準入力データを処理するプログラムを作る際に非常に便利だったりします。
__END__トークン以降に、テストしたいデータを貼り付けておけば、いちいち実行してからコンソールにデータを貼り付けるなんて面倒な事せずに済みますから!
使い方
というわけで、複数行の入力データを元にHashを作るという簡単な実装例を作ってみました。
プログラム
$_input = DATA #標準入力に切り替える場合、STDINに変更する h = {} while line = $_input.gets do (k, n) = line.split(" ") h.store(k, n) end p h __END__ 1 apple 2 orange 3 lemon 4 banana
実行結果
{"1"=>"apple", "2"=>"orange", "3"=>"lemon", "4"=>"banana"}
RubyのLoggerを使ってみる
どうも、パイソンです。今回はRubyのログ出力に関する簡単なメモです。
Loggerクラスの使い方
Rubyにはどうも標準でLoggerというログ出力用ライブラリが備わっているようです。
使い勝手としてはJavaのlog4jと似た風な感じかなーという印象。
プログラム
require 'logger' log = Logger.new('./logsample.log') log.debug("debug log") log.info("info log") log.warn("warn log") log.error("error log") log.fatal("fatal log") #INFO以上のレベルのみ出力 log.level=Logger::INFO log.debug("debug log") log.info("info log") log.warn("warn log") log.error("error log") log.fatal("fatal log")
出力結果(logsample.log)
# Logfile created on 2017-04-16 23:45:50 +0900 by logger.rb/47272 D, [2017-04-16T23:45:50.273300 #9628] DEBUG -- : debug log I, [2017-04-16T23:45:50.273300 #9628] INFO -- : info log W, [2017-04-16T23:45:50.273300 #9628] WARN -- : warn log E, [2017-04-16T23:45:50.273300 #9628] ERROR -- : error log F, [2017-04-16T23:45:50.273300 #9628] FATAL -- : fatal log I, [2017-04-16T23:45:50.273300 #9628] INFO -- : info log W, [2017-04-16T23:45:50.273300 #9628] WARN -- : warn log E, [2017-04-16T23:45:50.273300 #9628] ERROR -- : error log F, [2017-04-16T23:45:50.273300 #9628] FATAL -- : fatal log
という感じで出力することができます。
なお、
log = Logger.new('./logsample.log')
のところを
log = Logger.new(STDOUT)
に変えてみると、標準出力に出すことが出来ます。
Loggerクラスの機能等
そういや、ログローテート機能はどうなってんだろ?と思い調べてみたらちゃんと機能として備わっている模様。
参考URL
Rubyist Magazine - 標準添付ライブラリ紹介 【第 2 回】 Logger
今更ながら、標準で大抵必要な機能が備わっているのがRubyの良さだと感心する。
RubyのTimeクラスを使ってみた
どうも、パイソンです。今回はRubyのTimeクラスのメモです。
Timeクラス
Rubyで現在時間を取るにはTimeクラスを使う。
使い方もRubyらしく結構シンプル。
プログラム
puts Time.new t = Time.new puts "今日は" + t.year.to_s + "年" + t.month.to_s + "月" + t.day.to_s + "日です。"
実行結果
2017-04-15 22:49:35 +0900 今日は2017年4月15日です。
雑感
Rubyとは直接関係無いけど、時間クラスの仕様って結構落とし穴になったりすることがあるので、慎重に仕様確認する必要があると思います。
たとえば私、昔お仕事でperlを使ってたことがありまして、、
my (undef, undef, undef, $mday,$mon,$year) = localtime();
とすると、$yearに+1900しないと西暦にならんかったり、$monに至っては、1月の癖に0を返却したりするんだからね!!
ということで、今回はそんな懐かしい思い出がよみがえったという記事でした。
参考URL
Rubyでベンチマークを取る
Rubyについて調べてると、そこかしこのサイトでRubyプログラムの処理速度を出しているところがあったんですが、どうすれば出せるかを理解してなかったので、ちゃんと調べた結果をメモしておきます。
Rubyでベンチマーク測定
なんとRubyでは、標準で処理速度測定用のモジュールが用意されていました。
うーん、今更ながらRuby便利すぎる。
プログラム
require 'benchmark' Benchmark.bm 10 do |x| x.report "concat1" do str1 = "" 100000.times do str1 += "str" end end x.report "concat2" do str2 = "" 100000.times do str2 << "str" end end end
実行結果
user system total real concat1 2.184000 3.510000 5.694000 ( 5.697419) concat2 0.000000 0.015000 0.015000 ( 0.018270)
とりあえず、サンプルがてら文字列連結を+演算子で処理するバージョンと、<<演算子で処理するバージョンを比較。
その結果、まあやはりというか、処理速度という点では破壊的バージョンの方が優れているという事になりましたとさ。
sortとsort!の違い
どうも、パイソンです。
今日は、Rubyでsortのやり方を調査した時の内容をメモしておきます。
sortとsort!
「ruby sort」とググッたら出てきたリファレンスを眺めてると、並び替えをするメソッドにもsortと、sort!という2通りがある模様。
はぁ、、?「!」に何の意味があるんじゃ?ということで確認してみると、、
「!」はメソッド名の一部です。慣用的に、 同名の(! の無い)メソッドに比べてより破壊的な作用をもつメソッド(例: tr と tr!)で使われます。
https://docs.ruby-lang.org/ja/2.1.0/doc/symref.html
ということらしい。
要は「!」付きのメソッドはオブジェクトに作用するから気を付けましょうねー。的なノリなんだろうか。。
そこで、試しに書いて見たのがこんなプログラム。
numbers1 = [2, 6, 5, 4, 9, 8, 10, 3, 7, 1] p numbers1.sort #=>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] p numbers1 #=>[2, 6, 5, 4, 9, 8, 10, 3, 7, 1] numbers2 = [2, 6, 5, 4, 9, 8, 10, 3, 7, 1] p numbers2.sort! #=>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] p numbers2 #=>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ま、確かにsort!のほうはオブジェクトそのものを書き換えてるんだなーというのが分かりました。
「!」無しのメソッドは安全?
そんなことなら、「!」無しのメソッドは元のオブジェクトを編集したらあかんのかい!という疑問も浮かんでくるもの。
が、そんな事は無かった。どうも「!」の有無はあくまで目安的な物に過ぎないというのが現状である模様。
参考URL
あくまで、こんな慣習があるんですよー、という程度に覚えておこう。
Rubyの文字列連結メモ
どうも、パイソンです。
今日は、Rubyの文字列連結で少しハマった事をメモしておきます。
Rubyの文字列連結演算子
まずは、基本から。
Rubyで文字列を連結する方法には、+演算子を使う方法と、<<演算子を使う方法があります。
#文字列連結テスト str1 = "ABC" + "DEF" puts str1 #"ABCDEF"と出力 str2 = "abc" << "def" puts str2 #"abcdef"と出力
+演算子と<<演算子の違い
どちらも文字列を連結しているだけのように見えますが、
という点で違いがあります。
いろんなサイトで調べてみたところ、「+演算子は処理速度が遅い。<<演算子は処理速度が速いけどオブジェクトを破壊するので気をつけましょう。」という感じのようです。
何に気をつけるの?
じゃぁ、オブジェクトを書き換える事で実際どんな事が起きるの?ということで少しサンプルを組んでみました。処理内容は、"A","B","C"の文字をn個繋げてできる全ての文字列の組み合わせを出力するというものです。
#+演算子で連結するVer def func1(str, depth) if depth == 0 puts str return end ["A", "B", "C"].each do |c| func1(str + c, depth -1) end end puts "func1を実行してみた結果" func1("", 2)
実行結果
func1を実行してみた結果 AA AB AC BA BB BC CA CB CC
このプログラムの+演算子を<<に変更してみましょう。
#<<演算子で連結するVer def func2(str, depth) if depth == 0 puts str return end ["A", "B", "C"].each do |c| func2(str << c, depth -1) end end puts "func2を実行してみた結果" func2("", 2)
実行結果
func2を実行してみた結果 AA AAB AABC AABCBA AABCBAB AABCBABC AABCBABCCA AABCBABCCAB AABCBABCCABC
と、まあ前の結果とは大違いの結果。。
要は再帰処理を使ってオブジェクトをスタックに積んでるつもりが、<<演算子を使ったのでひたすら一点のオブジェクトを書き換えてただけでした、というオチ。
雑感
当初Rubyおぼえたての私は、「<<のほうが早いんじゃん!」と単純に考えてましたが、やはりそれぞれの違いを理解して状況に応じ適切に使い分けるようにしないといけませんね。
Twitterはじめました
どうも、パイソンです。
はてなブログ連携用にアカウント作成しました。
— パイソン (@devsishow) 2017年4月11日
#はじめてのツイート
基本ブログ連携用ですが、なんか思いついたさいにつぶやくこともありますので、フォローしてくださったら嬉しいです。
んで、当面の活用方法としては、、
コイツを試して見るのが面白いかも。なんて思っております。
あー、でもなんかアイコンが無いとだいぶさみしい感じがするなー。(-_-;)
さっさと、なんかいいアイコン探しておこう。
では、また。