2008-03-29
Timeオブジェクトの等価でちょいはまった
Railsのテストでこんなメッセージが出た
<Sat Mar 29 20:05:49 +0900 2008> expected but
was
<Sat Mar 29 20:05:49 +0900 2008>.
あれ?なんでテスト落ちるんだろう。
irbで確認
irb(main):002:0> a = b = Time.now
=> Sat Mar 29 20:07:31 +0900 2008
irb(main):003:0> a == b
=> true
これは当たり前だ。同じオブジェクト指してるわけだし。
irb(main):004:0> a = Time.now
=> Sat Mar 29 20:08:18 +0900 2008
irb(main):005:0> b = Time.parse(a.to_s)
=> Sat Mar 29 20:08:18 +0900 2008
irb(main):006:0> a == b
=> false
げ。なんでfalse。
原因
簡単なことだった。
irb(main):004:0> a = Time.now
=> Sat Mar 29 20:08:18 +0900 2008
irb(main):005:0> b = Time.parse(a.to_s)
=> Sat Mar 29 20:08:18 +0900 2008
irb(main):006:0> a == b
=> false
irb(main):007:0> a - b
=> 0.859
irb(main):008:0> a.usec
=> 859000
irb(main):009:0> b.usec
=> 0
Time.nowには浮動小数点が含まれている。Time.parseとかlocalでやると、浮動小数点は0なんだ。
あ、今のは嘘だ。ごめんなさい(ノд`)Time.localはusecは指定できる。parseは無理のようです。
Time.local(year[, mon[, day[, hour[, min[, sec[, usec)
まぁ、Timeの値は浮動小数点が考慮されていることを忘れないようしよう。
ファイルテキストコンバーター
ファイル中のある文字列を別の文字列に変えたい
例えばこんなの。
- source.txt
■ファイル中のある文字列
・source.txt
これを下に変えたい。
- converted.txt
**ファイル中のある文字列 -source.txt
それ、ワンライナーでできるお(・∀・)!
はぁ?置換すりゃいいじゃんか。
って言われるのは承知で書きました。
ファイルテキストコンバーター
#!usr/local/bin/ruby -Ku class StringUtil require 'nkf' def self.encode(str,code = "u") NKF::nkf("-W -#{code} -m0",str) end end class TextConverter def self.encode_table(source,code = "u") keys = source.keys keys.inject({}){|h,k| h.merge(StringUtil.encode(k,code) => StringUtil.encode(source[k],code))} end def initialize(conversion_table) @conversion_table = conversion_table @target_regexp = Regexp.union(*(conversion_table.keys)) end def convert(str) str.gsub(@target_regexp) do |match| @conversion_table[match] end end end class FileTextConverter < TextConverter def convert(source) File.open(ARGV[0],"r") do |file| ext = File.extname(file.path) filename = File.basename(file.path,".*") File.open("#{filename}_converted#{ext}","w") do |new_file| file.each_line do |line| line = super(line) new_file.write(line) end end end end end
使うときはこんな感じ。
CONVERSION_TABLE = { "■" => "**", "・" => "-" }.freeze conversion_table = FileTextConverter.encode_table(CONVERSION_TABLE,ARGV[1]) ftc = FileTextConverter.new(conversion_table) ftc.convert(ARGV[0])
うーん。なんか、StringUtilを2回使っているところと、そもそもFileTextConverterの中にencode_tableメソッドがあるのが変な気がする。でも、下みたいにやるのはもっと変だしな。
class TextConverter def initialize(conversion_table,code = "u") @conversion_table = self.encode_table(conversion_table,code) @target_regexp = Regexp.union(*(conversion_table.keys)) end end
Converter#initializeは、conversion_tableをセットするものだから、conversion_table自体をいじるのはおかしいよなー。依存度があがる。渡されたものをただセットするだけのほうがいいと思う。
すると、そもそもTextConverterにencode_tableメソッドがあるのが変なのかな。
その変の感覚がまだ分かりきってないよね(ノд`)
というか、この使い捨てツール系に継承とか使うのどうなんだ・・・(汗)
追記:ワンライナーでやってみた
最近ワンライナー系の記事が2つもあったのでワンライナーでやってみました。
C:\>ruby -ne 'print $_.gsub("■","**").gsub("・","-")' "a.txt" > a_converted.txt
できた。ファイル読み込むのが簡単でいいなー。ワンライナー楽しい。
がー。すごい簡単にできた。
