From: "Jesús Gabriel y Galán" Date: 2010-09-21T02:38:39+09:00 Subject: Re: An elegant way... On Mon, Sep 20, 2010 at 7:10 PM, F. Senault wrote: > Hello everybody. > > I've written a method to solve a little problem, but I find my solution > really ugly.  So, I'm trying to find ways to improve it. > > The method takes one argument, an array containing a sorted list of > strings representing episodes numbers.  The episodes numbers are either > a number ('1', '12') or prefixed with a letter ('S1' for special 1).  My > goal is to find sequences in the numbers and join them with dashes : > >>> RAniDBTools.format_episodes_list([ '1', '2', '3', '4', '6', '7', '9', 'S1', 'S2' ]) > => "1-4, 6-7, 9, S1-S2" >>> RAniDBTools.format_episodes_list([ '1', '2', 'S3', 'S4', 'S5', 'O6' ]) > => "1-2, S3-S5, O6" > > Here's the code ; what can I do to improve this ? > > module RAniDBTools >  def RAniDBTools.format_episodes_list(list) >    lt = [] >    le = [] >    list.each do |epno| >      if ('0'..'9').include? epno[0,1] >        t = '' >        e = epno.to_i >      else >        t = epno[0..0] >        e = epno[1..-1].to_i >      end >      if lt.last == t >        max = le.last.max rescue le.last >        min = le.last.min rescue le.last >        if e == max + 1 >          le[-1] = (min..e) >        else >          le << e >          lt << t >        end >      else >        le << e >        lt << t >      end >    end >    f = [] >    le.each_with_index do |e, i| >      if e.is_a? Range >        f << "#{lt[i]}#{e.min}-#{lt[i]}#{e.max}" >      else >        f << "#{lt[i]}#{e}" >      end >    end >    f.join(', ') >  end > end I have no time to propose a complete solution. I'll leave to you adding the "Sx" and "Ox" processing. This is how I'd do it it they were all numbers: irb(main):004:0> list = [1,2,3,4,6,7,9,16,17] => [1, 2, 3, 4, 6, 7, 9, 16, 17] irb(main):018:0> result = [[list.first]] => [[1]] irb(main):023:0> list.each_cons(2) do |x,y| irb(main):024:1* if (x+1) == y irb(main):025:2> result.last << y irb(main):026:2> else irb(main):027:2* result << [y] irb(main):028:2> end irb(main):029:1> end => nil irb(main):030:0> result => [[1, 2, 3, 4], [6, 7], [9], [16, 17]] irb(main):031:0> s = "" => "" irb(main):034:0> res = result.map {|x| x.size == 1 ? x.to_s : "#{x.first}-#{x.last}"} => ["1-4", "6-7", "9", "16-17"] irb(main):035:0> res.join(",") => "1-4,6-7,9,16-17" For the other stuff, I would have a flag that tells me if I'm in the middle of a number, "S" or "O" run, and act accordingly. Hope this helps, Jesus.