List Slice
Synopsis
Retrieve a slice of a list.
Syntax
Exp₁ [ Exp₂ .. Exp₄]
Exp₁ [ Exp₂ , Exp₃ .. Exp₄]
where Exp₂ and Exp₄ are optional.
Types
//
Exp₁ | Exp₂ | Exp₃ | Exp₄ | Exp₁ [ Exp₂ .. Exp₄ ] or Exp₁ [ Exp₂ , Exp₃ .. Exp₄] |
---|---|---|---|---|
list[T₁] | int | int | int | list[T₁] |
Description
List slicing uses the integer values of Exp₂ and Exp₄ to determine the begin
(inclusive) and end
(exclusive)
of a slice from the list value L of Exp₁. Negative indices count from the end of the list backwards.
Using the second form, an extra index Exp₃ is given that determines the
index of the second element in the slice and establishes the step
between
successive elements in the slice. The default step
is 1.
If end
is smaller than begin
, the slice is constructed backwards.
Let Len
be the length of L and let N₂, N₃ and N₄ be the respective values of the expressions
Exp₂, Exp₂ and Exp₂ when they are present.
The slice parameters begin
, end
, and step
are determined as follows:
- Exp₂:
If Exp₂ is absent, then
begin = 0
. Otherwise, if N₂ >= 0 thenbegin = N₂
elsebegin = N₂ + Len
. - Exp₄:
If Exp₄ is absent, then
end = Len
. Otherwise, if N₄ >= 0, thenend = N₄
elseend = N₄ + Len
. - Exp₃:
If Exp₃ is absent, then if
begin < end
thenstep = 1
elsestep = -1
. Otherwise, ifbegin < end
, thenstep = N₃ - begin
elsestep = begin - N₃
.
Now, the constraints 0 <= begin < Len
and 0 < end < Len
should hold,
otherwise the exception IndexOutOfBounds
is thrown.
The slice consists of the elements L[begin]
, L[begin+step]
, L[end - step]
.
When begin >= end
, the elements are listed in reverse order.
Examples
Consider the list L = [0, 10, 20, 30, 40, 50, 60, 70, 80];
as running example.
Here is a view on L that will help to correlate positive and negative indices:
i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
L[i] | 0 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 |
-i | -9 | -8 | -7 | -6 | -5 | -4 | -3 | -2 | -1 |
Some common use cases (with begin
<= end
):
Slice | Means: |
---|---|
L[begin..end] | elements with indices begin through end-1 |
L[begin..] | elements with indices begin through the rest of the list |
L[..end] | elements with indices from the beginning through end-1 |
L[..] | the whole list |
L[-1] | last element of the list |
L[-2..] | the last two elements of the list |
L[..-2] | all elements except the last two. |
Let's put this into practice now.
rascal>L = [0, 10, 20, 30, 40, 50, 60, 70, 80];
list[int]: [0,10,20,30,40,50,60,70,80]
Slices with begin < end
rascal>L[1..3];
list[int]: [10,20]
rascal>L[1..]; // empty end => end of list
list[int]: [10,20,30,40,50,60,70,80]
rascal>L[..3]; // empty begin => first element of list
list[int]: [0,10,20]
rascal>L[..]; // both empty => whole list
list[int]: [0,10,20,30,40,50,60,70,80]
Slices with begin >= end
rascal>L[3..1]; // slice contains elements with indices 3 and 2 (in that order)
list[int]: [30,20]
rascal>L[3..3]; // empty slice when begin == end
list[int]: []
Slices with negative begin or end:
rascal>L[2..-2]; // equivalent to L[2..7]
list[int]: [20,30,40,50,60]
rascal>L[2..7];
list[int]: [20,30,40,50,60]
rascal>L[-4..-2]; // equivalent to L[5..7]
list[int]: [50,60]
rascal>L[5..7];
list[int]: [50,60]
Slices with an explicit second index:
rascal>L[1,3..6];
list[int]: [10,30,50]
rascal>L[5,3..];
list[int]: [50,30,10]
Slices not do go "out of bounds". Instead they just stop at the end or beginning:
rascal>L[..10];
list[int]: [0,10,20,30,40,50,60,70,80]
rascal>L[..-11];
list[int]: [0]