tags:

views:

385

answers:

4

Let's say I have a Ruby array

a = [1, 2, 3, 4]

If I want all but the first item, I can write a.drop(1), which is great. If I want all but the last item, though, I can only think of this way

a[0..-2]   # or
a[0...-1]

but neither of these seem as clean as using drop. Any other built-in ways I'm missing?

+10  A: 

I'm not saying this is any better...

>> a = t
=> [1, 2, 3, 4]
>> a.first a.size - 1
=> [1, 2, 3]

or a.take 3 or a.first 3

or do a.pop which will return the last and leave the array with everything before it

or make the computer work for its dinner: a.reverse.drop(1).reverse

or

>> class Array
>>   def clip n=1
>>     take size - n
>>   end
>> end
=> nil
>> a
=> [1, 2, 3, 4]
>> a.clip
=> [1, 2, 3]
>> a = a + a
=> [1, 2, 3, 4, 1, 2, 3, 4]
>> a.clip 2
=> [1, 2, 3, 4, 1, 2]
DigitalRoss
Adding a method to `Array` seems like the best approach to me. Most projects end up with a `core_ext.rb` file with little extensions like this. Some libraries are practically _all_ extensions like this: `ActiveSupport` for example.
thenduks
That's interesting, I've wondered how common it is. What do people think about poetry mode?
DigitalRoss
the `self` is unnecessary here.
Peter
@Peter: You're right, but sometimes it's nice to be explicit. Personal preference.Are you going to accept this answer?
thenduks
+1  A: 

Have you tried "take"

a.take(3)
Mike Buckbee
in general, this is `a.take(a.size - 1)`; yes, I considered this option.
Peter
+2  A: 

Out of curiosity, why don't you like a[0...-1]? You want to get a slice of the array, so the slice operator seems like the idiomatic choice.

But if you need to call this all over the place, you always have the option of adding a method with a more friendly name to the Array class, like DigitalRoss suggested. Perhaps like this:

class Array
    def drop_last
        self[0...-1]
    end
end
Mirko Froehlich
it just seems like lots of clutter, when drop is so clean. it's not a big deal, but hard to confirm at a brief glance that it is exactly right. I prefer your name, `drop_last`, by the way...
Peter
A: 

a[0...-1] seems like the best way. The array slicing syntax was created for exactly this purpose...

Alternatively, if you don't mind modifying the array in place, you could just call a.pop:

>> a = [1, 2, 3, 4]
>> a.pop
>> a
=> [1, 2, 3]
dbr