Rubyで連続数字をハイフンでつなぐよ
かなり古い記事だけどRubyを使って
連続数字をハイフンでつなぐ方法が出てたよ
Rubyでどう書く?:連続した数列を範囲形式にまとめたい - builder
要するにスペース区切りの数字列を
数字が連続する場合にその箇所をハイフンにする
という話だよ
"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."
解答例が出てたけどなんかしっくり来なかったので
自分なりの違う方法を考えてみたよ
まず数字文字列を数字の配列に変換するよ
str = "1 3 4 5 7" nums = str.scan(/\d+/).map(&:to_i) # => [1, 3, 4, 5, 7]
次にこれを
配列のインデックスに対応付けて配置し直すよ
nums.inject([]) { |arr, n| arr[n-1] = n; arr } # => [1, nil, 3, 4, 5, nil, 7]
これで数字が連続しないところにはnilが入るよ
次にnilのところで配列を分けるよ
nums = nums.chunk { |n| !n.nil? || nil }.to_a # => [[true, [1]], [true, [3, 4, 5]], [true, [7]]]
Enumerable#chunkを使うよ
そのブロックでは要素がnilの場合はnilを返すようにして
その要素を捨てるよ
次に各要素の長さに応じた加工を施して文字列にするよ
nums = nums.map { |_, gr| gr.size>1 ? "#{gr.first}-#{gr.last}" : "#{gr.first}" } # => ["1", "3-5", "7"]
最後にこれをつないで完成だよ
nums.join(', ') + '.' # => "1, 3-5, 7."
まとめると次のようになるよ
やっぱりRubyは便利だね!
id:smilerubyさんから
Enumerable#slice_beforeを使った例を頂いたので
併せて載せておくよ
def hyphenize(str) nums = str.scan(/\d+/).map(&:to_i).sort nums.slice_before(num: nums.first) { |e, prev| prev[:num], prevprev = e, prev[:num] prevprev.succ != prev[:num] }.map{ |e| e.minmax.uniq * '-' } * ', ' + '.' end hyphenize("1 3 4 5 7") # => "1, 3-5, 7."
e.minmax.uniq*'-'がステキだよね!
(追記:2012-1-7) id:smilerubyさんの案を参考に一部を訂正、追記しました。