Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby task: joining numbers to intervals

Tags:

ruby

I've got an array of uniq numbers. Like this: [1,2,3,4,7,8,10,12]. It can be unsorted. What I need is to get intevals for this array:

intervals_for [1,2,3,4,7,8,10,12]
#=> "1-4, 7-8, 10,12"

I've got my own solution:

def intervals_for(array)
  array.sort!
  new_array = []
  array.each do |a|
    if new_array.last and a == new_array.last.last+1
      new_array.last << a
    else
      new_array << [a]    
    end
  end
  new_array.map{|a| a.size > 1 ? "#{a.first}-#{a.last}" : a.first}.join(", ")
end

But I think somewhere here is more clean solution

like image 451
fl00r Avatar asked Oct 21 '10 12:10

fl00r


2 Answers

here's mine, using ver 1.9.1

def torange(a)
  r=[];s=a[0]
  a.uniq.sort!.each_cons(2) do |a|
      r<<[s,a[0]] and s=a[1] if a[1]-a[0]!=1
  end
  left=a.index(s)
  r<<[a[left..-1][0],a[left..-1][-1]]
end

torange([1,2,3,4,7,8,10,12]).each do |x|
  puts x[0]==x[1] ? "#{x[0]}" : "#{x[0]}-#{x[1]}"
end

output

$ ruby test.rb
1-4
7-8
10
12
like image 75
ghostdog74 Avatar answered Oct 06 '22 00:10

ghostdog74


Here is my one-liner:

array = [-10, -9, -1, 0, 1, 2, 3, 4, 10, 11, 15, 133]
array.uniq.sort.inject([]){ |a, e| a[-1] && a[-1].last && a[-1].last == e-1 ? a[-1] = (a[-1].first..e) : a << (e..e); a }
#=> [-10..-9, -1..4, 10..11, 15..15, 133..133]

And little monkeypatchng

class Array
  def.collect_to_ranges
    self.uniq.sort.inject([]){ |a, e| a[-1] && a[-1].last && a[-1].last == e-1 ? a[-1] = (a[-1].first..e) : a << (e..e); a }
  end
end

array = [1,2,3,4,5,6,7,8, 10]
array.collect_to_ranges
#=> [1..8, 10..10]
like image 36
fl00r Avatar answered Oct 05 '22 23:10

fl00r