Here's a pattern that seems relatively efficient and easier to understand.
public static List<Object> slice(List<Object> input, Integer ge, Integer l)
{
List<Object> output = input.clone();
for (Integer i = 0; i < ge; i++) output.remove(0);
Integer elements = l - ge;
while (output.size() > elements) output.remove(elements);
return output;
}
If you want to support negative index, just add this linethese lines at the beginning of the method:
if (ge < 0) ge += input.size();
if (l < 0) l += input.size();
And running it through this script yields the proper input/output combos:
List<String> data = new List<String> { 'Banana', 'Orange', 'Lemon', 'Apple', 'Mango' };
List<String> sliced = (List<String>)slice(data, 1, 3);
system.debug(data); // (Banana, Orange, Lemon, Apple, Mango)
system.debug(sliced); // (Orange, Lemon)
List<String> data = new List<String> { 'zero', 'one', 'two', 'three' };
List<String> sliced = (List<String>)slice(data, 1, 3);
system.debug(data); // (zero, one, two, three)
system.debug(sliced); // (one, two)