Skip to content

Instantly share code, notes, and snippets.

@darrencauthon
Forked from jmeirow/to_range.rb
Created November 26, 2012 14:06
Show Gist options
  • Save darrencauthon/4148375 to your computer and use it in GitHub Desktop.
Save darrencauthon/4148375 to your computer and use it in GitHub Desktop.
create array of ranges from array of individual values
class Array
def to_range
highs = self.select { |x| self.include?(x+1) == false }.sort_by { |x| x }
lows = self.select { |x| self.include?(x-1) == false }.sort_by { |x| x }
(0...lows.count).map { |i| lows[i]..highs[i] }
end
end
require 'minitest/spec'
require 'minitest/autorun'
require_relative 'to_range'
describe '#to_range' do
describe "empty set" do
it "should return an empty set" do
[].to_range.count.must_equal 0
end
end
describe "one item" do
[1, 2, 1001].each do |value|
it "should return one range" do
result = [value].to_range
result.count.must_equal 1
result[0].must_equal value..value
end
end
end
describe "two consecutive items" do
[[1,2], [3,4], [10000, 10001]].each do |array|
it "should return one range" do
result = [array[0],array[1]].to_range
result.count.must_equal 1
result[0].must_equal array[0]..array[1]
end
end
end
describe "two nonconsecutive items" do
[[1,3], [3, 5], [566, 1001]].each do |array|
it "should return two ranges for each item" do
result = array.to_range
result.count.must_equal 2
result[0].must_equal array[0]..array[0]
result[1].must_equal array[1]..array[1]
end
end
end
describe "three consecutive items" do
[[1,2,3], [2,3,4], [100,101,102]].each do |array|
it "should return one range" do
result = array.to_range
result.count.must_equal 1
result[0].must_equal array.first..array.last
end
end
end
describe "joe's example" do
it "should return one range" do
result = [1,2,3,4,5,100,101,102,400,401,402,403,404,405,406].to_range
result.count.must_equal 3
result[0].must_equal 1..5
result[1].must_equal 100..102
result[2].must_equal 400..406
end
end
describe "unordered example" do
it "should return one range" do
result = [4,3,100,102,1000,1,2,101].to_range
result.count.must_equal 3
result[0].must_equal 1..4
result[1].must_equal 100..102
result[2].must_equal 1000..1000
end
end
describe "with dates" do
it "should return ranges just like with integers" do
result = ['2012-11-26', '2012-11-27', '2012-11-28', '2013-01-01', '2013-01-02', '2013-01-04'].
map { |x| Date.parse(x) }.to_range
result.count.must_equal 3
result[0].must_equal Date.parse('2012-11-26')..Date.parse('2012-11-28')
result[1].must_equal Date.parse('2013-01-01')..Date.parse('2013-01-02')
result[2].must_equal Date.parse('2013-01-04')..Date.parse('2013-01-04')
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment