slice_beforeで
id:seuzoさんの『連続した日付を範囲形式でまとめる』を読んで自分も作ってみた。
いつまでも使い方が覚えられないEnumerable#slice_beforeを使ってみる。
Ruby1.9.2p136です。
# coding: UTF-8 require 'date' lists = " 2010-12-31 , 2011-01-01 , 2011-01-02 ,2011-01-10, 2011-03-02,2011-03-01,2011-02-28,2011-03-03,2011-03-05,2012-0-00 " sorted = [*lists].flatten.flat_map{|list| list.chomp.split(/,/)} .map{|e| Date.parse(e.strip) rescue nil}.compact.sort prev = sorted.first result = sorted.slice_before{|cur| prev, prevprev = cur, prev; prevprev.succ != prev} .map{|a| a.minmax.uniq.map{|e| e.strftime("%m/%d")}.join("〜".encode(Encoding.find("locale")))} .join("、".encode(Encoding.find("locale"))) puts result # =>12/31〜01/02、01/10、02/28〜03/03、03/05
数値もやってみる。
# coding: UTF-8 def list2array(*lists, list_delimiter) [*lists].flatten.flat_map{|list| list.chomp.split(list_delimiter).map(&:strip)} end def array_of(array, converter) array.map(&converter).compact.sort end def to_rangef(array, formatter) prev = array.first groups = array.slice_before do |cur| prev, prevprev = cur, prev prevprev.succ != prev end groups.map(&formatter) end if __FILE__ == $0 lists = DATA.lines.to_a list_delimiter = /,/ array = list2array(lists, "11.1,12.3,13.5,14.7,15.9", list_delimiter) converters = { Date: lambda{|e| require 'date'; Date.parse(e) rescue nil}, Fixnum: lambda{|e| e.to_i.zero? ? (Integer(e) rescue nil) : e.to_i}, String: lambda{|e| e.to_s rescue nil}, } array = array_of(array, converters[:Fixnum]) formatters = { Date: lambda{|a| require 'date'; a.minmax.uniq.map{|e| e.strftime("%m/%d")}.join("..")}, Fixnum: lambda{|a| a.minmax.uniq.map(&:to_s).join("..")}, String: lambda{|a| a.minmax.uniq.map{|e| %!"%s"!%e}.join("..")}, } groups = to_rangef(array, formatters[:Fixnum]) delimiter = "、".encode(Encoding.find("locale")) puts groups.join(delimiter) # =>0..2、4..7、9..15 end __END__ 1,2,4 6 5 7.0,9.0,10 0 a, ?a
眠くてGiveUp(-_-)zzz