番号文字列をインクリメントする
"Z10-036K"みたいな文字列があったとして、"Z10-999K"の次は"Z11-000K"になってほしいよねということで書いてみました。
ソース(というほどのものではない)
Stringクラスに defineするので既存のメソッドをオーバーライトしないように、なるべくダサい名前にしてみました。(ここが一番時間かかったところ)
class String def to_numstr self.unpack("C*").map{|e|e.chr=~/\d/&&$&}.to_s end def to_numstr_next s = (self.to_numstr.to_i + 1).to_s return self + s if s == "1" ret = "" self.size.times do |i| if ?0 <= self[i] && self[i] <= ?9 ret += s[0..0] s = s[1..-1] || "" else ret += self[i..i] end end ret + s end end
to_numstr
文字列の中から数字だけをピックアップして文字列として返します。数字が含まれないと""が返ります。
"Z10-999K".to_numstr #=> "10999" "Z-K".to_numstr #=> ""
to_numstr_next
文字列の数字部分をインクリメントして返します。数字のMAXまでいって桁が増えたらフォーマットがずれます。数字が含まれない場合は文字列に"1"を付けて返します。
"Z10-999K".to_numstr_next #=> "Z11-000K" "Z-K".to_numstr_next #=> "Z-K1" "Z99-999K".to_numstr_next #=> "Z10-000K0" "Z10-000K1".to_numstr_next #=> "Z10-000K2"
まとめ(ではない)
会員番号などで無駄に頭にアルファベットがついているのがあって、コツコツ先頭から数字以外を取って、数字を処理してから戻したりしていたんですが、途中に入っているケースなんかが出てきて、「どういうコード設計しとるんじゃい!責任者出てこい!」という感じになったので、心の平穏を保つために書きました。