tags:

views:

39

answers:

1

I often want to take out a subpart from an Enumerable. The subpart is sometimes at the beginning and sometimes the end of the original Enumerable instance, and the length used to specify the subpart is sometimes that of the subpart and sometimes its complement. That gives four possibilities, but I only know how to do three of them. Is there a way to do the fourth one?

  1. Getting the first n elements: [1, 2, 3, 4, 5].first(3) #=> [1, 2, 3] or [1, 2, 3, 4, 5].take(3) #=> [1, 2, 3]

  2. Dropping the first n elements: [1, 2, 3, 4, 5].drop(3) #=> [4, 5]

  3. Getting the last n elements: [1, 2, 3, 4, 5].last(3) #=> [3, 4, 5]

  4. Dropping the last n elements: [1, 2, 3, 4, 5].some_method(3) #=> [1, 2]

+1  A: 

There is no built-in way that does exactly this, but it's easy to use slice with a negative index:

[1, 2, 3, 4, 5][0...-3] # => [1, 2]

and you could roll your own if you do that often:

class Array
  def rdrop(n)
    self[0...-n]
  end
end

[1, 2, 3, 4, 5].rdrop(3) # => [1, 2]

Note: last is not a method of Enumerable; the only way rdrop could be one would be to build the array first (like Enumerable#sort does)...

Marc-André Lafortune
Very pretty. I thought of a negative slice, but forgot `...` for the exclusive slice. That left me adding one to the number *before* making it negative, and all seemed ugly again.
Telemachus
Thanks for the suggestion and the note. I also had forgotten about the exclusive slice.
sawa