質問: 配列の中に、 複数の番号を格納しているとき、 それをまとめて表示する「綺麗なロジック」を 教えていただけないでしょうか? ``` data=["1","2","3","5","7","8","9","10","11","12","15","16"] ``` このようなデータがある時に ``` 1~3,5,7~12,15,16 ``` という 「人が見てきれいな」出力を作りたいのですが、 「綺麗なロジック」が思いつきません。 熟練の方、 短く、早く、美しいロジックを ご教授願えないでしょうか? 私がrubyやVBAを使っているのでサンプルはrubyですが、 rubyやVBAが第一希望ですが、他の言語でもOKです。 ですがが、 「言語特有の(モジュール等を使った)ロジック」でない方がありがたいです。
回答: RubyであればEnumerable#chunk_whileが使えます。 上のリンク先のマニュアルにまさしくそのような出力をするための例が載っています。それを参考にまとめて書くと次のようになります。 ``` data = ["1", "2", "3", "5", "7", "8", "9", "10", "11", "12", "15", "16"] puts data.map(&:to_i) .chunk_while { |a, b| b == a.succ } .map { |x| x.size < 3 ? x : "#{x.first}~#{x.last}"} .join(',') ``` ですが、chunk_whileのような隣同士をみてグルーピングするという関数やメソッドが用意されている言語は見当たらないです(group_byのようなグルーピングであればHaskellやLINQでみらえますが)。ということで、chunk_whileでしていることをEnumerable#injectで置き換えます。 ``` data = ["1", "2", "3", "5", "7", "8", "9", "10", "11", "12", "15", "16"] puts data.map(&:to_i) .inject([]) { |a, x| a.empty? || a.last.last.succ != x ? a + [[x]] : a.take(a.size - 1) + [(a.last + [x])] } .map { |x| x.size < 3 ? x : "#{x.first}~#{x.last}"} .join(',') ```