"Sputnik" help  
Sputnik Help
Language Reference - Datatypes - Slicing

Slicing

This is not to be confused with Array Splicing.

Sputnik's [] bracket can also be used as a splice operator and provides a powerful and flexible way to extract substrings from a string.

The syntax for the [] splice operator is as follows:

Note that the start and end indices are inclusive and exclusive, respectively. That means, for example, that [1:4] extracts characters at indices 1, 2, and 3.

In addition, the step size can be negative, which means the characters are extracted in reverse order. For example, [::-1] extracts the string in reverse order.

Here are some examples of how the [] splice operator works:


Main Information

Lists, character strings, byte strings and bit strings support various slicing and indexing possibilities through the [] operator.

We are going to use the _T predefined macro:

Indexing elements with positive integers is zero based. Negative indexes are transformed to positive by adding the number of elements to them, therefore -1 is the last element. Indexing with list of integers is possible as well so [1, 2, 3][_T(-1, 0, 1)] is [3, 1, 2].

Slicing is an operation when parts of sequence is extracted from a start position to an end position with a step value. These parameters are separated with colons enclosed in square brackets and are all optional. Their default values are [start:maximum:step=1]. Negative start and end characters are converted to positive internally by adding the length of string to them. Negative step operates in reverse direction, non-single steps will jump over elements.

This is quite powerful and therefore a few examples will be given here:

Positive indexing a[x]
It'll simply extracts a numbered element. It is zero based, therefore "abcd"[1] results in "b".

Negative indexing a[-x]
This extracts an element counted from the end, -1 is the last one. So "abcd"[-2] results in "c".

Cut off end a[:to]
Extracts a continuous range stopping before to. So [10,20,30,40][:-1] results in [10,20,30].

Cut off start a[from:]
Extracts a continuous range starting from from. So [10,20,30,40][-2:] results in [30,40].

Slicing a[from:to]
Extracts a continuous range starting from element from and stopping before to. The two end positions can be positive or negative indexes. So [10,20,30,40][1:-1] results in [20,30].

Everything a[:]
Giving no start or end will cover everything and therefore results in a complete copy.

Reverse a[::-1]
This gives everything in reverse, so "abcd"[::-1] is "dcba".

Slicing [from:to]
Extracts a continuous range starting from element from and stopping before to. The two end positions can be positive or negative indexes. So [10,20,30,40][1::-1] results in [20,10].

Stepping through a[from:to:step]
Extracts every stepth element starting from from and stopping before to. So "abcdef"[1:4:2] results in "bd". The from and to can be omitted in case it starts from the beginning or end at the end. If the step is negative then it's done in reverse.

Slice starts from the beginning and extracts every stepth element a[from::step]
If step is negative, the extraction is done in reverse. For example, "abcdef"[::2] returns "ace" because it starts from the beginning and extracts every 2nd element, and "abcdef"[::-1] returns "fedcba" because it starts from the end and extracts every element in reverse. The double colon notation can also be combined with a start and end index, as in "abcdef"[1::2], which returns "bdf", starting from the second element and extracting every 2nd element. If the start and end indices are omitted, the slice will cover everything, resulting in a complete copy.

Extract multiple elements a[list]
Extract elements based on a list. So "abcd"[[1,3]] will be "bd".

The fun start with nested lists and tuples, as these can be used to create a matrix. The examples will be given for a two dimensional matrix for easier understanding, but this also works in higher dimensions.

Extract row a[x]
Given a [[1,2],[3,4]] matrix [0] will give the first row which is [1,2]

Extract row range a[:,from:to]
Given a [[1,2],[3,4],[5,6],[7,8]] matrix [1:3] will give [[3,4],[5,6]]

Extract column a[:,to]
Given a [[1,2],[3,4]] matrix [:,1] will give the first column of all rows which is [[1],[3]]
Another idea would be given a [[1,2],[3,4]] matrix [:,1] squish [<<] will give the first column of all rows which is [1,3]

Extract column from a[:,from:]
Given a [[1,2,3,4,5,6],[7,8,9,10,11,12]] matrix [:,3:] will give [[4,5,6],[10,11,12]]

Extract column range a[:,from:to]
Given a [[1,2,3,4],[5,6,7,8]] matrix [:,1:3] will give [[2,3],[6,7]]

Extract column range a[:,from:to:step]
Given a [[1,2,3,4,5,6],[7,8,9,10,11,12]] matrix [:,1:6:2] will give [[2,4,6],[8,10,12]]

Reverse column a[::,-1]
Given a [[1,2],[3,4]] matrix [::,-1] will give [[2,1],[4,3]]

And it works for list of indexes, negative indexes, stepped ranges, reversing, etc. on all axes in too many ways to show all possibilities.

Basically it's just the indexing and slicing applied on nested constructs, where each nesting level is separated by a comma.

The [] splice operator provides a flexible and powerful way to extract substrings from a string in Sputnik.


Array Examples

In addition to working with strings, the [] splice operator can also be used with arrays. This allows for easy manipulation of arrays.

Heres a few basic examples:

printr [1, 2, 3][_T(-1, 0, 1)];
printr [10,20,30,40][:-1];
printr [10,20,30,40][-2:];
printr [10,20,30,40][1:-1];
printr [10,20,30,40][1::-1];
// PRINTS
// Array
// (
//     [0] => 3
//     [1] => 1
//     [2] => 2
// )
// Array
// (
//     [0] => 10
//     [1] => 20
//     [2] => 30
// )
// Array
// (
//     [0] => 30
//     [1] => 40
// )
// Array
// (
//     [0] => 20
//     [1] => 30
// )
// Array
// (
//     [0] => 20
//     [1] => 10
// )

Another large example this time using column mode:

printr [[1,2],[3,4],[5,6],[7,8]][1:3]; // [[3,4],[5,6]];
printr [[1,2],[3,4]][::,-1]; // [[2,1],[4,3]]
printr [[1,2],[3,4]][:,1]; // [[1],[3]]
printr [[1,2],[3,4]][:,1][<<]; // [1,3]
printr [[1,2,3,4,5,6],[7,8,9,10,11,12]][:,1:6:2]; // [[2,4,6],[8,10,12]]
printr [[1,2,3,4,5,6],[7,8,9,10,11,12]][:,3:]; // [[4,5,6],[10,11,12]]
// PRINTS
// Array
// (
//     [0] => Array
//         (
//             [0] => 3
//             [1] => 4
//         )
//     [1] => Array
//         (
//             [0] => 5
//             [1] => 6
//         )
// )
// Array
// (
//     [0] => Array
//         (
//             [0] => 2
//             [1] => 1
//         )
//     [1] => Array
//         (
//             [0] => 4
//             [1] => 3
//         )
// )
// Array
// (
//     [0] => Array
//         (
//             [0] => 1
//         )
//     [1] => Array
//         (
//             [0] => 3
//         )
// )
// Array
// (
//     [0] => 1
//     [1] => 3
// )
// Array
// (
//     [0] => Array
//         (
//             [0] => 2
//             [1] => 4
//             [2] => 6
//         )
//     [1] => Array
//         (
//             [0] => 8
//             [1] => 10
//             [2] => 12
//         )
// )
// Array
// (
//     [0] => Array
//         (
//             [0] => 4
//             [1] => 5
//             [2] => 6
//         )
//     [1] => Array
//         (
//             [0] => 10
//             [1] => 11
//             [2] => 12
//         )
// )

Check out Array Splicing for a few extra things to do with arrays.


String Examples

Here is a clever use of slicing to find out if a number is odd or even:

Function EvenOrOdd($num)
{
    return "eovdedn"[$num % 2::2];
}

say EvenOrOdd(1);  // odd
say EvenOrOdd(20); // even

This functoin determines if a given number is even or odd using an unconventional approach. The % operator is utilized to calculate the starting point in the string "eovdedn" and ::2 is employed to read the string while skipping every two characters. Consequently, the function extracts 'odd' for odd numbers and 'even' for even numbers. The examples say EvenOrOdd(1); and say EvenOrOdd(20); showcase the correct functionality, correctly identifying 'odd' for 1 and 'even' for 20.

Heres a large example covering just about all variations:

say "reverse"[::0]; // ""
say "reverse"[::1]; // "reverse"
say "reverse"[::2]; // "rvre"
say "reverse"[::3]; // "ree"
say "reverse"[::4]; // "rr"
say "reverse"[::5]; // "rs"
say "reverse"[::6]; // "re"
say "reverse"[::7]; // "r"
say "reverse"[::8]; // "r"
say "reverse"[::15]; // "r"
say "reverse"[::-1]; // "esrever"
say "reverse"[::-2]; // "ervr"
say "reverse"[::-3]; // "eer"
say "reverse"[::-4]; // "ev"
say "reverse"[::-5]; // "ee"
say "reverse"[::-6]; // "er"
say "reverse"[::-7]; // "e"
say "reverse"[::-15]; // "e"
say "reverse"[:6]; // "revers"
say "reverse"[:7]; // "reverse"
say "reverse"[:8]; // "reverse"
say "reverse"[:15]; // "reverse"
say "reverse"[:-0]; // ""
say "reverse"[:-1]; // "revers"
say "reverse"[:-2]; // "rever"
say "reverse"[:-3]; // "reve"
say "reverse"[-8:]; // "reverse"
say "reverse"[-15:]; // "reverse"
say "reverse"[0:0]; // ""
say "reverse"[0:1]; // "r"
say "reverse"[0:2]; // "re"
say "reverse"[-3:15]; // "rse"
say "reverse"[-4:15]; // "erse"
say "reverse"[-4:3]; // ""
say "reverse"[-4:4]; // "e"
say "reverse"[-4:5]; // "er"
say "reverse"[-4:6]; // "ers"
say "reverse"[0:0]; // ""
say "reverse"[0:1]; // "r"
say "reverse"[3:7]; // "erse"
say "reverse"[3:8]; // "erse"
say "reverse"[4:0]; // ""
say "reverse"[4:5]; // "r"
say "reverse"[4:6]; // "rs"
say "reverse"[4:7]; // "rse"
say "reverse"[4:8]; // "rse"
say "reverse"[5:0]; // ""
say "reverse"[0:-6]; // "r"
say "reverse"[-0:7]; // "reverse"
say "reverse"[-1:1]; // ""
say "reverse"[1:-1]; // "evers"
say "reverse"[-1:-1]; // ""
say "reverse"[-1:2]; // ""
say "reverse"[1:-2]; // "ever"
say "reverse"[-1:-2]; // ""
say "reverse"[-1:3]; // ""
say "reverse"[1:-3]; // "eve"
say "reverse"[3:-2]; // "er"
say "reverse"[-3:-2]; // "r"
say "reverse"[-3:3]; // ""
say "reverse"[3:-3]; // "e"
say "reverse"[-3:-3]; // ""
say "reverse"[-3:4]; // ""
say "reverse"[3:-4]; // ""
say "reverse"[-3:-4]; // ""
say "reverse"[-6:5]; // "ever"
say "reverse"[6:-5]; // ""
say "reverse"[-6:-5]; // "e"
say "reverse"[-6:6]; // "evers"
say "reverse"[6:-6]; // ""
say "reverse"[-6:-6]; // ""
say "reverse"[-6:7]; // "everse"
say "reverse"[6:-7]; // ""
say "reverse"[-6:-7]; // ""
say "reverse"[-6:8]; // "everse"
say "reverse"[6:-8]; // ""
say "reverse"[1:1:8]; // ""
say "reverse"[1:2:8]; // "e"
say "reverse"[1:3:1]; // "ev"
say "reverse"[1:3:8]; // "e"
say "reverse"[1:4:1]; // "eve"
say "reverse"[1:4:2]; // "ee"
say "reverse"[1:4:3]; // "e"
say "reverse"[1:-3:1]; // "eve"
say "reverse"[1:-3:2]; // "ee"
say "reverse"[1:-3:3]; // "e"
say "reverse"[2:-1:1]; // "vers"
say "reverse"[2:-1:2]; // "vr"
say "reverse"[2:-1:3]; // "vs"
say "reverse"[1:1:-1]; // ""
say "reverse"[2:1:-1]; // "v"
say "reverse"[2:2:-1]; // ""
say "reverse"[3:1:-1]; // "ev"
say "reverse"[3:1:-2]; // "e"
say "reverse"[3:3:-1]; // ""
say "reverse"[1::1]; // "everse"
say "reverse"[7::7]; // ""
say "reverse"[1::-1]; // "er"
say "reverse"[-1::1]; // "e"
say "reverse"[-1::-1]; // "esrever"
say "reverse"[1::-2]; // "e"
say "reverse"[-1::2]; // "e"
say "reverse"[3::-2]; // "ee"
say "reverse"[-3::2]; // "re"
say "reverse"[-3::-2]; // "rvr"
say "reverse"[3::-3]; // "er"
say "reverse"[-3::3]; // "r"
say "reverse"[-3::-3]; // "re"
As you can see it can be fairly powerful.
Binary Examples

In addition to working with strings, the [] splice operator can also be used with binary variables. This allows for easy manipulation of data within binary data structures.

Heres a large example showing many variations:

$bin = (Binary)"reverse";

say $bin[::0]; // ""
say $bin[::1]; // $bin
say $bin[::2]; // "rvre"
say $bin[::3]; // "ree"
say $bin[::4]; // "rr"
say $bin[::5]; // "rs"
say $bin[::6]; // "re"
say $bin[::7]; // "r"
say $bin[::8]; // "r"
say $bin[::15]; // "r"
say $bin[::-1]; // "esrever"
say $bin[::-2]; // "ervr"
say $bin[::-3]; // "eer"
say $bin[::-4]; // "ev"
say $bin[::-5]; // "ee"
say $bin[::-6]; // "er"
say $bin[::-7]; // "e"
say $bin[::-15]; // "e"
say $bin[:6]; // "revers"
say $bin[:7]; // $bin
say $bin[:8]; // $bin
say $bin[:15]; // $bin
say $bin[:-0]; // ""
say $bin[:-1]; // "revers"
say $bin[:-2]; // "rever"
say $bin[:-3]; // "reve"
say $bin[-8:]; // $bin
say $bin[-15:]; // $bin
say $bin[0:0]; // ""
say $bin[0:1]; // "r"
say $bin[0:2]; // "re"
say $bin[-3:15]; // "rse"
say $bin[-4:15]; // "erse"
say $bin[-4:3]; // ""
say $bin[-4:4]; // "e"
say $bin[-4:5]; // "er"
say $bin[-4:6]; // "ers"
say $bin[0:0]; // ""
say $bin[0:1]; // "r"
say $bin[3:7]; // "erse"
say $bin[3:8]; // "erse"
say $bin[4:0]; // ""
say $bin[4:5]; // "r"
say $bin[4:6]; // "rs"
say $bin[4:7]; // "rse"
say $bin[4:8]; // "rse"
say $bin[5:0]; // ""
say $bin[0:-6]; // "r"
say $bin[-0:7]; // $bin
say $bin[-1:1]; // ""
say $bin[1:-1]; // "evers"
say $bin[-1:-1]; // ""
say $bin[-1:2]; // ""
say $bin[1:-2]; // "ever"
say $bin[-1:-2]; // ""
say $bin[-1:3]; // ""
say $bin[1:-3]; // "eve"
say $bin[3:-2]; // "er"
say $bin[-3:-2]; // "r"
say $bin[-3:3]; // ""
say $bin[3:-3]; // "e"
say $bin[-3:-3]; // ""
say $bin[-3:4]; // ""
say $bin[3:-4]; // ""
say $bin[-3:-4]; // ""
say $bin[-6:5]; // "ever"
say $bin[6:-5]; // ""
say $bin[-6:-5]; // "e"
say $bin[-6:6]; // "evers"
say $bin[6:-6]; // ""
say $bin[-6:-6]; // ""
say $bin[-6:7]; // "everse"
say $bin[6:-7]; // ""
say $bin[-6:-7]; // ""
say $bin[-6:8]; // "everse"
say $bin[6:-8]; // ""
say $bin[1:1:8]; // ""
say $bin[1:2:8]; // "e"
say $bin[1:3:1]; // "ev"
say $bin[1:3:8]; // "e"
say $bin[1:4:1]; // "eve"
say $bin[1:4:2]; // "ee"
say $bin[1:4:3]; // "e"
say $bin[1:-3:1]; // "eve"
say $bin[1:-3:2]; // "ee"
say $bin[1:-3:3]; // "e"
say $bin[2:-1:1]; // "vers"
say $bin[2:-1:2]; // "vr"
say $bin[2:-1:3]; // "vs"
say $bin[1:1:-1]; // ""
say $bin[2:1:-1]; // "v"
say $bin[2:2:-1]; // ""
say $bin[3:1:-1]; // "ev"
say $bin[3:1:-2]; // "e"
say $bin[3:3:-1]; // ""
say $bin[1::1]; // "everse"
say $bin[7::7]; // ""
say $bin[1::-1]; // "er"
say $bin[-1::1]; // "e"
say $bin[-1::-1]; // "esrever"
say $bin[1::-2]; // "e"
say $bin[-1::2]; // "e"
say $bin[3::-2]; // "ee"
say $bin[-3::2]; // "re"
say $bin[-3::-2]; // "rvr"
say $bin[3::-3]; // "er"
say $bin[-3::3]; // "r"
say $bin[-3::-3]; // "re"

Just like with String above it the binary variables support it all too.


Class Examples

In addition, classes can override the behavior of the [] splice operator by implementing the __Slice Magic Function. This method takes in the type of slice operation being performed (none, to, from, from-to, from-to-step, from-step, reverse, or clone), the starting offset, the ending index, and the step value. The class can then use this information to manipulate the underlying data and return the spliced data or a new instance of the class.

Here's an example implementation of a class that overrides the __Slice:

Class Slicer
{
    my $arr;
    Function __Construct($array)
    {
        $arr = $array;
    }
    Function __Slice($type, $offset, $end, $step)
    {
        say "Slice offset $offset end $end step $step";
        switch ($type)
        {
            case @SliceTypeNone:
                say "Type None";
                break;
            case @SliceTypeTo:
                say "Type To";
                break;
            case @SliceTypeFrom:
                say "Type From";
                break;
            case @SliceTypeFromTo:
                say "Type FromTo";
                break;
            case @SliceTypeFromToStep:
                say "Type FromToStep";
                break;
            case @SliceTypeFromStep:
                say "Type FromStep";
                break;
            case @SliceTypeReverse:
                say "Type Reverse";
                break;
case @SliceTypeColumnTo: say "Type Column To"; break; case @SliceTypeColumnFrom: say "Type Column From"; break; case @SliceTypeColumnFromTo: say "Type Column FromTo"; break; case @SliceTypeColumnFromToStep: say "Type Column FromToStep"; break; case @SliceTypeColumnFromStep: say "Type Column FromStep"; break; case @SliceTypeColumnReverse: say "Type Column Reverse"; break; case @SliceTypeClone: say "Type Clone"; break; } return array(); // splied array can be returned or new class instance } } $a = new Slicer(["A" rr "F"]); $a[::-1]; $a[3::-1]; $a[4:5]; $a[4:5:7]; $a[:8]; $a[9:]; // PRINTS // Slice offset -1 end 0 step -1 // Type Reverse // Slice offset 3 end 0 step -1 // Type FromStep // Slice offset 4 end 5 step 1 // Type FromTo // Slice offset 4 end 5 step 7 // Type FromToStep // Slice offset 0 end 8 step 1 // Type To // Slice offset 9 end 0 step 1 // Type From

For further reading check out Slicing Assignments.


Contact
Cheryl (uberfox@hotmail.com)
Homepage
http://ubersoft.org