From 429a1a875b06cf91d7d2b167d2174555012a071f Mon Sep 17 00:00:00 2001 From: Ryan Duryea Date: Fri, 21 Oct 2016 11:39:48 -0700 Subject: [PATCH] Add Array#to_ranges I needed this code for a project and figured I'd offer it up to facets I originally found this code at https://dzone.com/articles/convert-ruby-array-ranges but it didn't actually work as described, so I fixed it. --- lib/core/facets/array/to_ranges.rb | 30 ++++++++++++++++++++++++++++++ test/core/array/test_to_ranges.rb | 13 +++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 lib/core/facets/array/to_ranges.rb create mode 100644 test/core/array/test_to_ranges.rb diff --git a/lib/core/facets/array/to_ranges.rb b/lib/core/facets/array/to_ranges.rb new file mode 100644 index 00000000..cad2dae8 --- /dev/null +++ b/lib/core/facets/array/to_ranges.rb @@ -0,0 +1,30 @@ +class Array + + # Convert an array of values (which must respond to #succ) to an + # array of ranges. + # + # [3,4,5,1,6,9,8].to_ranges => [1..1,3..6,8..9] + # + # CREDIT: Adapted and debugged by Ryan Duryea + # from https://dzone.com/articles/convert-ruby-array-ranges + + def to_ranges + array = self.compact.uniq.sort + ranges = [] + if !array.empty? + # Initialize the left and right endpoints of the range + left, right = array.first, nil + array.each do |obj| + # If the right endpoint is set and obj is not equal to right's successor + # then we need to create a range. + if right && obj != right.succ + ranges << Range.new(left,right) + left = obj + end + right = obj + end + ranges << Range.new(left,right) + end + ranges + end +end diff --git a/test/core/array/test_to_ranges.rb b/test/core/array/test_to_ranges.rb new file mode 100644 index 00000000..02b9591d --- /dev/null +++ b/test/core/array/test_to_ranges.rb @@ -0,0 +1,13 @@ +covers 'facets/array/to_ranges' + +test_case Array do + + method :to_ranges do + + test do + [3,4,5,1,6,9,8].to_ranges.assert == [1..1,3..6,8..9] + end + + end +end +