How to get all elements from a list without the last element?
groovy
Solution
The best way to take all elements but the last one, in my opinion, is to use the `take` method:
def list = ['a', 'b', 'c']
assert list.take(list.size() - 1) == ['a', 'b']
It behaves properly in the corner case where size == 1:
def list = ['one']
assert list.take(list.size() - 1) == []
Though I'd prefer it to throw an exception in the case size == 0, but the behavior is not that bad:
def list = []
assert list.take(list.size() - 1) == []
You can also use `list[0..<list.size()-1]` (your third example) and it will behave the same except for the empty list, in which case it will throw an `ArrayIndexOutOfBoundsException`, but i think is not as readable as the `take` counterpart.
Another acceptable solution is using `list[0..-2]` (your last example), which i think looks much more elegant, but unfortunately breaks when size == 1 with an `ArrayIndexOutOfBoundsException`.
In your examples (i'll assume that you meant to use 0 as the starting index instead of 1 if you wanted to include all elements but the last one):
`lines[0..lines.size()-1]` is equivalent to `lines[0..-1]` because the `getAt(Range)` method of lists will treat ranges with negative indexes the same way as`getAt(Integer)` does, i.e. as accessing the `(list.size() + negativeIndex)`'th element of the list. Therefore `list[0..-1]` is the same as saying "from first element to last" and it's the same as copying the list; and `list[-1..0]` is the same as "from last to first" and it's equivalent to `list.reverse()` :)
The problem with the other non-inclusive range example is that the non-inclusive ranges are being evaluated before the list access and they evaluate to an incorrect inclusive range. For example, `0..<-2` evaluates to `0..-1`, and that's why it's returning all the elements. `0..<-1` evaluates to `0..0` and it returns only the first element.
Notice that the empty range is a special case. It's denoted as `0..<0` and it doesn't have an inclusive equivalent (so Groovy won't do any magic conversion here). And that's why `list[0..<list.size()-1]` works when size == 1 (the range evaluates to the empty range) while `list[0..-2]` doesn't :)
Problem
The following Groovy code ``` lines = ['0','1','2','3','4','5'] println lines[1..lines.size()-1] println lines[1..-1] println lines[1..<lines.size()-1] println lines[1..<-1] println lines[1..<-2] println lines[1..-2] ``` produces this output: ``` [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] [1, 2, 3, 4] [1, 0] [1, 2, 3, 4, 5] [1, 2, 3, 4] ``` Since `-1` is the index of the last element in the list, the first two make sense (ranges in Groovy include the end element instead of omitting it as everywhere else in Java :-( ) Line #3 is the desired output (list without first and last element). I'm worried about the output #4: Why do I get `[1, 0]` for `1..-1`? Also `[1, 2, 3, 4, 5]` for the range `1..<-2` seems wrong. Why does that happen?