かわじ、です。
初めまして、かな?
> 1,2,3,5,7,8,10,12,14,15,16,17
>
> の様なソート済番号のリストを,
>
> 1-3,5,7-8,10,12,14-17
>
> の様な表現に直すスクリプトを Perl でつくりました.
> そんなわけで「お題」として如何でしょう.
Ruby ですが、このメールの末尾に付けておきます。
使い方は、以下の通り。
-> [1,2,3,5,7,8,10,12,14,15,16,17].to_r.join(',')
"1-3,5,7-8,10,12,14-17"
to_r というメソッドの命名のいい加減さと、Range#to_s の挙動を変更して
しまっていますが、そこは本当に使いたい人が修正して下さるとして、
メリットは、Arrayの構成要素は数字に限らず、Rangeの要素になりうる
オブジェクト(つまり、<=> と succ のメソッドの両方あるオブジェクト)で
あれば、どのようなオブジェクトも要素に出来るというところです(ただし、
もちろん、Array内は全て同じクラスのオブジェクトであることが前提です)。
例えばで、Date オブジェクトですと
( - で連結しているので分かりにくいですが)、
-> [
-> Date.new(2002,1,1),
-> Date.new(2002,1,2),
-> Date.new(2002,1,5),
-> Date.new(2002,1,7),
-> Date.new(2002,1,8),
-> Date.new(2002,1,9),
-> ].to_r.join(',')
"2002-01-01-2002-01-02,2002-01-05,2002-01-07-2002-01-09"
という感じです。
ざくっと作ったので、もっと速いバージョンをどなたか作ってくださることで
しょう・・・
class Range
def to_s
[self.begin,self.end].join('-')
end
end
class Array
def to_r
result = []
from = nil
to = nil
self.compact.uniq.sort.each{|a|
if to and to.succ == a
from ||= to
elsif to
result << (from ? Range.new(from,to) : to)
from = nil
end
to = a
}
result << (from ? Range.new(from,to) : to)
end
end