Rubyでどう書く?:連続した数列を範囲形式にまとめたい
三浦義太郎(KBMJ)
2008/04/17 08:00
「連続した数列を範囲形式にまとめたい」と題しまして、並んだ数字を確認用にわかりやすくする為に、ソートされた数字の列をハイフンで繋ぐ方法を解説したいと思います。
問題
並んだ数字を確認用にわかりやすくする為に、ソートされた数字の列をハイフンで繋ぐにはどうすればよいでしょうか?
数列は見づらいものです。ただ数字を並べているだけでは、ソートしてもどの数字が抜けているかを判断するために、順に目で追ってチェックする必要があります。
rubyではそういった配列をわかりやすく表現する為に「1...3」と表現する方法が用意されているのですが、利用者は、「1 2 3 5」というような数字の羅列を入れてくるかもしれません。さて、rubyでこれらをハイフンで繋ぐためにはどのように処理する必要があるでしょうか。
仕様
- 数値は、半角スペースで区切られた文字列で渡されます。
- 続いている部分は、最初の数値と最後の数値を-(ハイフン)で繋いだ表記にします。
- 連続が1回の場合(前の数も後ろの数も連続でない)は、-(ハイフン)では繋ぎません。
- 出力は、「,」(カンマ)と半角スペースで区切られた文字列でなければなりません。
例
- "1 2 3" => "1-3."
- "1 2 3 5 7 8" => "1-3, 5, 7-8."
- "1 3 4 5 7" => "1, 3-5, 7."
回答例
a = $*[0].split(' ').map{|i|i.to_i}+[nil]
i = a[0]
p a.inject([a[0].to_s]){|r, v|
if i != v
r << r.pop + "-#{i-1}" if 2 <= i - r.last.to_i
break r unless v
i = v
r << i.to_s
end
i +=1
r
}.join(', ')+'.'
判定用の変数を配列の値と違うものになるまで増分していき、連続を判定しています。連続でなくなった段階で配列の値を出力用の配列と判定用の変数に入れて同様の処理を繰り返していきます。判定用の変数の値と出力用の配列の最後の値(連続開始の値)の差が2以上の場合に「-[数字]」の文字列を追加します。
- $*にはコマンドライン引数の値の配列が入ります。
injectは以前のブロックの実行結果を引数と受け取って順次処理していくことができる関数です。あまり使われていないようですが、結構便利な関数です。
p [1,2,3,4,5].inject(0) {|result, item| result + item } => 15
ほかによい方法があればコメントしてみてください。
- 今日のトップ記事
- 2日前
- 3日前
- 4日前
- 6日前
- 7日前
- ホワイトペーパー
- 話題のタグ
小技
PHP
Webアプリケーション開発
Ruby on Rails
Internet Explorer
Tips
仮想化
SOA
Firefox
フレームワーク
Mozilla
開発環境
Google
HTML
Database
Apple
C/C++
XHTML
Ajax
Linux
Apache
オープンソース
iPod touch
MySQL
イロハ
Adobe
Java
RIA
Python
Mac OS X
Leopard
JavaScript
IDE
Eclipse
Firefox 3
Off Topic
Windows
入門
Ruby
まとめ
ブラウザ
Flash
iPhone
Webデザイン
ライブラリ
リファレンス
Safari
CSS
Microsoft
server
話題のタグを見る »
Firefox 3が対応したdisplayプロパティの値(3) - inline-table
MSもアドビも学生さんに開発ソフトを無償提供
「Economist」のトップページがリニューアル
あなたがプログラムを理解できない10の理由:第2回
新APIまもなく登場--Google Developer Day 2008の見所とは?
仮想化によるコスト削減を見える化:オンラインTCOカリキュレータ
内部統制対策を実現するIT運用管理ツール
リスティング広告における競争優位性の維持
-Simplify IT- ITをシンプルに 連載第2回