Skip to content

Instantly share code, notes, and snippets.

@JEG2
Forked from pragdave/gist:570434
Created September 8, 2010 18:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JEG2/570556 to your computer and use it in GitHub Desktop.
Save JEG2/570556 to your computer and use it in GitHub Desktop.
Trying to remove some noise, but I don't think I helped.
input = [ 1, 2, 3, 4, 5, 8, 9, 11, 12, 13, 15 ]
# divide the input into runs of consecutive numbers
last = input.first
s = input.slice_before(lambda { |i| [i != last + 1, (last = i)].first })
# replace runs of 3 or more with first-last
p s.map {|runs| runs.size < 3 ? runs : "#{runs.first}-#{runs.last}"}
.flatten
.join(', ') # => 1-5, 8, 9, 11-13, 15
@JEG2
Copy link
Author

JEG2 commented Sep 20, 2010

Isn't there quite a bit of overlap between with_next/prev and each_cons(2)?

@eregon
Copy link

eregon commented Sep 20, 2010

Isn't there quite a bit of overlap between with_next/prev and each_cons(2)?

You are right about #with_next, I made a mistake in the code
(I actually wanted to yield each element with the next one, including the last one, with itself or nil).

I indeed felt first to use #each_cons, but the behavior is different:
#each_cons will only yield (size-1) times but #with_prev will yield size times.

This leads to the problem to know what is the "previous" of the first. I choose to have the first, as you do.

As we use #slice_before, we need to yield each element, and say we want a new slice at the first
(with #each_cons and considering it as (last,element), the first will be dropped).

[1,3,4,6,7,8].each_cons(2).slice_before { |l,e| e != l.succ }.map { |group| group.map { |l,e| e } }
# => [[3, 4], [6, 7, 8]] 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment