Chapter 10. Sequences

A JavaFX Script sequence is a special kind of data structure that, like an array in Java, represents an ordered list of items of the same type. But unlike Java arrays, JavaFX Script sequences are not objects. Like arrays, however, they hold elements (individual items in the sequence) of the same type.

Syntax

var sequence_name : datatype[];

or

var sequence_name : datatype[] = [value1, value2 .. value n];

or

var sequence_name = [value1, value2 .. value n];

The examples in Listing 10-1 show several ways to create and initialize a sequence.

Example 10.1. Different ways of defining a sequence

1.    var emptySequence : Integer[];
2.     println(emptySequence);    // []
3.
4.    var intSequence : Integer[] = [2,4,6,8,10];
5.    println(intSequence);        // [ 2, 4, 6, 8, 10 ]
6.
7.    var inferenceSequence = ["Praveen", 'Girish' ,"Cheran" , 'Rabi' , "Lawrence" ];
8.    println(inferenceSequence);    // [ Praveen, Girish, Cheran, Rabi, Lawrence ]

In line 1 we create an empty sequence, which is represented as brackets: [ ]. In line 4 we define an Integer sequence named intSequence and initialize it. As you can see, a sequence is initialized by specifying its elements within the brackets. In line 7, we define an Inference-type sequence called inferenceSequence; this sequence holds String elements.

The sizeof Operator

After creating a sequence, we commonly need to know the number of elements it holds. So JavaFX Script provides a unary operator called sizeof, which returns the number of elements in a sequence.

Syntax

sizeof sequence name;

The example in Listing 10-2 demonstrates the usage of the sizeof operator.

Example 10.2. Using the sizeof operator

1.    var emptySequence:Integer[];
2.    println("sizeof emptySequence = {sizeof emptySequence }"); // sizeof emptySequence = 0
3.
4.    var inferenceSequence = ["Praveen",'Girish', "Cheran" , 'Rabi' , "Lawrence" ];
5.    println("sizeof inferenceSequence = {sizeof inferenceSequence}"); // sizeof inferenceSequence = 5

Line 2 prints 0 for emptySequence, since it doesn't have any elements, and line 5 prints the size of inferenceSequence as 5, since that variable holds five elements.

Accessing the Elements of a Sequence

Once you create a sequence, you may need to access its elements, either in a specific order, such as from the first element to the last, or randomly. You access an element of a sequence by specifying its index within square brackets ([ ]).

Syntax

sequence_name[index] ;

The example in Listing 10-3 demonstrates how to access the elements of a sequence.

Example 10.3. Accessing the elements of a sequence

1.    var teamMembers : String[] = [
2.        "Praveen", "Lawrence", "Girish","Rabi","Cheran","Srini","Blessan"
3.    ];
4.    println("My team members");        // My team members
5.    for( i in [0.. sizeof teamMembers - 1] )
6.    println(teamMembers[i]);    //     Praveen
                                         Lawrence
                                         Girish
                                         Rabi
                                         Cheran
                                         Srini
                                         Blessan

In Listing 10-3, we declare a String sequence teamMembers. Each element of the sequence is accessed using its index, as in line 12. To access the element, we have used a for range expression, which starts from zero and ends with sizeof teamMembers −1.

Alternatively, you can use the following statements to access the elements of the sequence:

for( i in names  )
println(i);

Elements of a sequence can also be accessed randomly. For example, if you want to access the third element of the teamMembers sequence, you specify it as teamMembers[2], which returns the value girish.

Note

Sequences are "zero based," which means they always starts from zero and end with a value of sizeof the sequence minus 1. For example, if the sequence has 100 elements, the first element is accessed by sequence[0] and the last element by sequence[99].

Nested Sequences

You might come across a situation where you need to combine sequences. When you do this, the JavaFX Script compiler automatically flattens all the sequences to form a single sequence.

The example in listing 10-4 demonstrates the nesting of sequences.

Example 10.4. Sequence nesting

1.    var numSeq1 : Integer[] = [1,2,3];
2.    var numseq2 : Integer[] = [6,7,8,9,10];
3.    var numSeq3 : Integer[] = [ numSeq1 , 4,5, numseq2 ];
4.    println(numSeq1);    // [ 1, 2, 3 ]
5.    println(numSeq2);    // [ 6, 7, 8, 9, 10 ]
6.    println(numSeq3);    // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

First we declare three sequences. The last sequence (numSeq3) holds numSeq1 and numSeq2 as individual elements (to form a nested sequence), as well as its own elements. When JavaFX Script executes line 3 it flattens numSeq1 and numSeq2 to form a single sequence, (numSeq3). This can be seen in the line 6 output statement.

Creating a Sequence Using a Range Expression

Range expressions can be used to create either Integer or Number sequences. You have already seen range expression in Chapter 4, "Operators and Expressions." Usually a range expression consists of a starting number, ending number, and optional step value. The step value may be either positive or negative (depending on the requirement); the default step value is 1.

Syntax

var sequence_name: datatype[] = [start value ..end value  step value];

The example in Listing 10-5 demonstrates how to create sequences using range expressions.

Example 10.5. Creating sequences using range expressions

1.    var intSeq : Integer[] = [1..10]; // default step positive 1
2.    println(intSeq );    // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
3.    var intSeq1 : Integer[] = [0..100 step 10]; // step  10
4.    println(intSeq1);    // [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ]
5.    var emptySeq : Integer[] = [100..0];  //empty sequence, since step is missing
6.    println(emptySeq);    // [ ]
7.    var intSeq2 : Integer[] = [100..0 step −10 ];
8.    println(intSeq2);    // [ 100, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0 ]
9.    var numSeq : Number [] = [0.5 .. 5.0 step 0.5];  //  number sequence
10.    println(numSeq);    // [ 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0 ]

In line 1, we declare an intSeq sequence whose value ranges from 1 to 10. Since we have not specified the step value, its default value of 1 is used. In line 3, we declare an intSeq1 sequence, whose value ranges from 0 to 100 with a step value of 10. Next, in line 5, we declare an emptySeq sequence, whose range of values is from 100 to 0. Since the starting number of the range is greater than the end number and we have not specified the step value of this sequence, the result of this range expression is zero; hence, the sequence is empty. To avoid this type of empty sequence creation, it is mandatory to specify the step value of the range expression used to create the sequence. The correct version of the empty sequence is specified in line 7, with the sequence creation intSeq2. Finally, line 9 shows a Number sequence whose range value is from 0.5 to 5.0 with the step value of 0.5.

When you compile the code in Listing 10-5, you will encounter a warning that the expression will return an empty sequence.

Note

It's a good practice to specify the step value when creating a sequence using a range expression.

Excluding the End Value in the Sequence

Until now, the sequences that you have created using range expressions included the end value that you specified in the range expression. In some situations, you may need to exclude the end value when creating a sequence using a range expression. To do this, use two dots and a less-than relation operator (..<) in the range expression.

Syntax

var sequence_name :  datatype [] = [start value .. end value  step value];

The example in Listing 10-6 demonstrates how to create a sequence that excludes the end value of its range expression.

Example 10.6. Creating a sequence that excludes the end value of the range expression

1.    var intSeq  : Integer[] = [1..< 10];
2.    println(intSeq ); // output [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
3.    var intSeq1 : Integer[] = [0..< 90 step 10];
4.    println(intSeq1); // output [ 0, 10, 20, 30, 40, 50, 60, 70, 80 ]

In this example, we declare two sequences and create them using range expressions. In line 1, we have a range expression generating numbers from 1 to 10. While generating the range numbers from 1 to 10 each time, the JavaFX Script compiler checks the condition that generated numbers must be less than 10. Once the generated number reaches 10, then your range expression is stopped, since the condition has failed and the resulting sequence range is from 1 to 9. In line 3, we declare a sequence whose range number is from 0 to 80 with the specified step value of 10. This sequence holds the decade values from 0 to 80, since the condition for this range expression is < 90 and the step value is 10.

Sequence Slicing

Sequence slicing provides access to portions of a sequence. That is, using this technique you create from an existing sequence either a new sequence or an expression that evaluates to a sequence. The newly created sequence elements will be within the range, or equal to the existing elements, of the existing sequence. Usually sequence slicing consists of a sequence name (the existing sequence) or another expression that evaluates to a sequence, followed by a pair of square brackets which has a starting index with an optional ending index separated by two dots (..) or two dots with a less-than relational operator (..<). If the ending index is omitted, JavaFX Script interprets it as accessing all the elements of the sequence started from the specified starting index to the sizeof the sequence minus one.

The example in Listing 10-7 demonstrates sequence slicing.

Example 10.7. Sequence slicing

1.    var s1 = [0..8];    // [0,1,2,3,4,5,6,7,8]
2.    var s2 = s1[4..];
3.    println(s2);        // [4,5,6,7,8]
4.    var s3 = s1s2[0..<];
5.    println(s3);        // [0,1,2,3,4,5,6,7 ]

In line 1, we declare a sequence s1, which holds the values from 0 to 8. In line 2, we are creating a new sequence (s2) from s1, and we are instructing the JavFX Script compiler to access all the elements of sequence s1 starting from index 4 to the sizeof s1 minus one. In line 4 we are creating a new sequence s3 from s2, in which we access all the elements of s2 starting from index 0 to the last element of s2 sequence; that is, from s2[0] to s2[sizeof s2-1].

Using a Predicate to Create a Subset of a Sequence

A predicate is a Boolean expression used to create a new sequence that is a subset of an existing sequence.

Syntax

var newSequence = existingSequence[variable | Boolean expression];

Here, existingSequence is the name of the existing sequence from which you are going to create a new sequence, which will be a subset of existingSequence, and assign it to newSequence. Notice the pair of square brackets ([ ]) that enclose a predicate in the format of a selection variable. Here, variable is just a placeholder within the square brackets that helps the compiler to evaluate Boolean expression. The vertical bar | character is used to visually separate the variable from Boolean expression. Finally, the Boolean expression specifies the criteria to be met before the current item will be copied into the new sequence.

The example in Listing 10-8 demonstrates creating a new sequence from an existing sequence using predicates.

Example 10.8. Creating a new sequence from an existing one using predicates

1.    var integerSequence : Integer[] = [1..10 ];
2.    println(integerSequence);    // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
3.    var subSequence1 = integerSequence[ n | n > 5 ];
4.    println(subSequence1);        // [ 6, 7, 8, 9, 10 ]
5.    var subSequence2 = integerSequence[ n | n < 5 ];
6.    println(subSequence2);        // [ 1, 2, 3, 4 ]
7.    var subSequence3 = integerSequence[ n | indexof n > 4 ];
8.    println(subSequence3);        // [ 6, 7, 8, 9, 10 ]
9.    var subSequence4 = integerSequence[ n | indexof n < 2 or indexof n > 7 ];
10.    println(subSequence4);        // [ 1, 2, 9, 10 ]
11.    var emptySequence = integerSequence[ n | n > 10 ];
12.    println(emptySequence);     // [ ]

Note

The difference between sequence slicing and sequence predicates is that in sequence slicing, a range expression is used to create a new sequence, whereas in sequence predicates the vertical bar and a Boolean expression are used to create a new sequence from an existing one.

Working with Sequences

So far, you have created sequences either by explicitly specifying the elements of the sequence or by using range expressions. JavaFX Script also allows you to insert and delete the elements of the sequence dynamically. The following operations can be performed on a sequence:

  • Inserting elements into the sequence

  • Deleting elements from the sequence

  • Reversing a sequence

Inserting an Element into a Sequence

An element can be inserted into a sequence dynamically using the insert and into keywords.

Syntax

insert element into sequence_name;

var  seq : Integer [] ;
insert 120 into seq;
insert 45 into seq;

In these statements we first create an empty Integer sequence, seq. in the later statements we insert the values 120 and 45 into the seq sequence. By default, elements are inserted at the end of a sequence. So when you print the seq sequence, you see the following output on the console:

[ 120 , 45 ]

Suppose you want to insert an element 75 as the first element of the sequence seq. To do that, you can use the following syntax:

Insert element before sequence_name[ index ] ;

insert 75 before seq[0];
insert 99 before seq[2];

In these statements, we are inserting the value 75 as the first element (seq[0]) and value 99 as the third element ( seq[2]). We do this by using the keyword before and specifying the index within the sequence where we want to insert. The before keyword instructs JavaFX Script that you need to insert the element before the specified index in the sequence. When you print this seq sequence, you'll see the following output on the console:

[ 75, 120, 99, 45 ]

You can insert an element after a specified element in a sequence; this is done using the keyword after.

Syntax

insert element after sequence_name[index];

For example, in the following statements:

insert 67 after seq[1];
insert 78 before seq[1];

we are inserting 67 as the third element and 78 as the last element of the sequence seq. The final output of the seq sequence is as follows:

[ 75, 120, 67, 99, 45, 78 ]

An element or value can also be inserted into a sequence by specifying a negative index.

The examples in Listing 10-9 show how to insert elements into a sequence by specifying the index in different forms.

Example 10.9. Different ways of inserting elements into a sequence dynamically

1.    var nums = [0..10];
2.    insert 65 after nums[sizeof nums+1];
3.    insert 23 after nums[sizeof nums];
4.    insert 77 after nums[sizeof nums - 1];
5.    insert 21 before nums[5];
6.    insert 97 after nums[0];
7.    insert 6 before nums[-1];
8.    insert 54 after nums[-2];
9.    println(nums);        // [ 54, 6, 0, 97, 1, 2, 3, 4, 21, 5, 6, 7, 8, 9, 10, 65, 23, 77 ]

We are not restricted to inserting only a single element into a sequence; we can also insert a sequence into an existing sequence. The resulting sequence will be flattened, as you learned in the "Nested Sequences" section of this chapter.

The example in Listing 10-10 demonstrates how to insert a sequence as an element into another sequence.

Example 10.10. Inserting a sequence as an element into a sequence

1.    var num : Integer[] = [1..4];
2.    var num1 : Integer[] = [5..10];
3.    insert num1 after num[2];
4.    println(num);         // [ 1, 2, 3, 5, 6, 7, 8, 9, 10, 4 ]

In this example, we declare two sequences, num and num1, using range expressions. In line 3 , we are inserting the num1 sequence after num[2].

Deleting an Element from a Sequence

Element of a sequence can be deleted dynamically, using the delete keyword. Following are different ways of deleting elements from a sequence:

  • Specifying the element of the sequence.

  • Specifying the index of the element in the sequence.

  • Deleting the whole sequence.

  • Deleting the elements using range expression.

Syntax

delete element from sequence_name;
delete     sequence_name[index];

The examples in Listing 10-11 demonstrate various ways of deleting elements from a sequence.

Example 10.11. Ways of deleting elements from a sequence

1.    var fruits : String [] = ["Applet" , "Mango" , "Orange", "Grapes"];
2.    delete "Mango" from fruits;   // deleting the element by specifying the element itself.
3.    delete fruits[1]; // deleting the element by specifying the index of the element
4.    println(fruits);      // [ Applet , Grapes ]

In line 1, we declare a String sequence named fruits with four elements. In line 2, we are deleting an element Mango from the sequence fruits; here from is a keyword that specifies from which sequence you are deleting the element. In line 3 , we are deleting the element by specifying its index within the sequence.

You can delete all of the elements in the sequence by specifying just the delete keyword followed by the sequence name, as in this example:

var fruits : String [] = ["Applet" , "Mango" , "Orange", "Grapes"];
delete fruits ;

Alternatively, you can use the following statement to delete all the elements of the sequence:

fruits = [];

You have learned how to create an Integer or Number sequence using a range expression. However, there may be situations where you need to delete a portion, or subset, of the sequence. In the previous the example of the fruits sequence, if you need to delete all the elements except Grapes, you can use the following statements:

delete fruits[0..2];

Note

The delete command only removes elements from the sequence; it does not delete the sequence from your script. You can still access the sequence and add new items to it as before.

Reversing a Sequence

JavaFX Script provides the reverse operator to reverse the order of elements in a sequence. The reverse operator produces a new sequence that contains the same elements as the original sequence but in reverse order.

Syntax

var sequence = reverse existingSequence;

The example in Listing 10-12 demonstrates how to reverse a sequence.

Example 10.12. Reversing a sequence

1.    var namesSeq : String[] = ["Lawrence" , "Yinhe" , "Praveen" , "Vimala Anne"];
2.    var reversedNameSeq = reverse namesSeq; // returns the reversed sequence of namesSeq
3.    println(reversedNameSeq);    // [ Vimala Anne, Praveen, Yinhe, Lawrence ]

Here, line 2 returns the reverse of sequence nameSeq to reversedNameSeq. This new sequence has the same elements as namesSeq but in the reverse order.

Sequences as Function Parameters

Unlike Java and its handling of arrays, JavaFX Script allows sequences to be used as function parameters. When a sequence is sent as a parameter to a function, its elements are read-only, like any other parameter to the function. That is, trying to change the elements of the sequence, inserting and deleting them dynamically, will result in a compile-time error. A script-level, package-level sequence can be accessed by any function. Sequences defined within a function, by contrast, cannot be accessed outside the function.

The example in Listing 10-13 demonstrates the implementation of a stack using a sequence; the sequence is passed as a parameter to the function.

Example 10.13. Implementing a stack using a sequence, by passing the sequence as a parameter to the function

1.    var stack: Integer[];
2.    function push(value : Integer){
3.        insert value into stack;
4.    }
5.
6.    function pop( ) {
7.        if(sizeof stack == 0 ){
8.            println("Stack underflow");
9.        }else {
10.            delete stack[sizeof stack −1];
11.        }
12.    }
13.
14.    function currentStackContent(stk : Integer[] ) {
15.        print(reverse stk);
16.    }
17.
18.    function peak() {
19.        if(sizeof stack == 0 ){
20.            println("Sorry..! there are no elements in the stack.");
21.        }else {
22.            println("
 { stack[sizeof stack −1] } is the topmost element
23.            in the stack.");
24.        }
25.    }
26.
27.    push(5);
28.    push(3);
29.    push(45);
30.    push(25);
31.    push(98);
32.    println("Content of the stack");    // Content of the stack
33.    currentStackContent(stack);        // [ 98, 25, 45, 3, 5 ]
34.    pop();
35.    peak();        //  25 is the topmost element in the stack.
36.    pop();
37.    println("Content of the stack");    // Content of the stack
38.    currentStackContent(stack );        // [ 45, 3, 5 ]

In Listing 10-13, the function push inserts an element into the stack; for each call of the push function the element is inserted at the end of the stack Integer sequence. The function pop deletes the last element of the stack using the sizeof operator before deleting the element, because we are checking for the availability of the element in the stack sequence. If the element is available, then the last element of the stack sequence is deleted. The function peep is used to check the last element of the stack sequence. The final and most interesting function is currentStackContent. It is used to display the elements of the stack sequence in reverse order (elements are printed in reverse order to achieve the last-in, first-out concept of stack implementation), where the sequence is sent as the parameter of the function, so that stack sequence is not modified.

Functions can also return a sequence as a return value. Let's modify the curentStackContent function so that it can return the reversed sequence.

function currentStackContent(stk : Integer[] ) : Integer[] {
    return reverse stk;
}

Function calls to currentStackContent should be modified accordingly.

Binding with Sequences

Unlike binding a variable, it is common to bind a sequence in JavaFX Script. When a variable is bound to an individual element of a sequence, any change either to the value of the element or its position (for example, when an element is inserted or deleted) is reflected in the bound variable.

The example in Listing 10-14 demonstrates how an element of a sequence is bound to a variable.

Example 10.14. Binding an element of a sequence to a variable

1.    var seq = [10, 20, 30];
2.    var z = bind seq[1];    // z is bound to seq[1]
3.    println(seq);        // [ 10,20,30 ]
4.    println("z={ z }");    // z=20
5.    insert 55 before seq[1];
6.    println(seq);        // [10,55,20,30 ]
7.    println(" z={ z }");    // z=55
8.    seq[1] = 38;
9.    println(seq);        //[10,38,20,30]
10.    println(" z={ z }");    //z=38
11.    delete seq[1];
12.    println(seq);        // [10,20,30]
13.    println(" z={ z }");    // z=20

In line 2, the variable z is bound to the second element of the seq sequence, seq[1]. When a new element is inserted at the second position of seq as in line 5 , the z value changes, reflecting the insertion of a new element at position seq[1]. The z value changes even when the element is updated, as in line 8.

You know that a sequence can be created using a range expression; we can also bind the sequence values to the range expression, Any changes that apply to the range expression directly will reflect the values of the sequence.

Listing 10-15 demonstrates how sequence values are bound to the range expression.

Example 10.15. Binding the sequence values to the range expression

1.    var num = 5;
2.    var seq1 : Integer[] = bind [1..num];
3.    println(seq1);    // [ 1,2,3,4,5 ]
4.    num = 10;
5.    println(seq1);    // [ 1,2,3,4,5,6,7,8,9,10 ]
6.    num = 6;
7.    println(seq1);   // [ 1,2,3,4,5,6 ]

Here, the seq1 is bound to the range expression, which goes from 1 to the value of num. As the value of num changes, the seq1 sequence values also change, as in lines 1, 4, and 6.

Just as binding can be applied between two variables, it can also be applied between two sequences. Any changes that occur to the source sequence, whether by inserting a new element, deleting an element, or any other change to the existing elements in the sequence, are reflected by changes in the destination sequence. In fact, even bidirectional binding can be applied between sequences, as demonstrated by the example in Listing 10-16.

Example 10.16. Binding applied between two sequences

1.    var seq1  = [1..5];
2.    println(seq1);        // [ 1, 2, 3, 4, 5 ]
3.    var seq2  = bind seq1 with inverse;
4.    println(seq2);          // [ 1, 2, 3, 4, 5 ]
5.    insert 100 before seq1[3];
6.    println(seq1);        // [ 1, 2, 3, 100, 4, 5 ]
7.    println(seq2);        // [ 1, 2, 3, 100, 4, 5 ]
8.    insert 555 into seq2;
9.    println(seq1);        // [ 1, 2, 3, 100, 4, 5, 555 ]
10.    println(seq2);        // [ 1, 2, 3, 100, 4, 5, 555 ]
11.    delete 5 from seq1;
12.    println(seq1);        // [ 1, 2, 3, 100, 4, 555 ]
13.    println(seq2);        // [ 1, 2, 3, 100, 4, 555 ]

javafx.util.Sequences Utility Functions

The javafx.util.Sequences class in JavaFX Script contains various functions for manipulating sequences. All the functions in this javafx.util.Sequences class are nonmutative; that is, they do not change the input parameters, but create new instances for output.

Following are the functions of the Javafx.util.Sequences class; you can see their descriptions in the API documentation:

  • sort(seq)

  • sort(seq,comparator)

  • binarySearch(seq, key);

  • binarySearch(seq,key,comparator)

  • indexByIdentity(seq,key)

  • indexOf(seq,key)

  • isEqualByContentIdentity(seq1, Seq2)

  • max(seq)

  • max(seq, comparator)

  • min(seq)

  • min(seq,comparator)

  • nextIndexByIdentity(seq,key,pos)

  • nextIndexOf(seq,key,pos)

  • reverse(seq)

  • shuffle(seq)

Summary

A sequence is an ordered list of items of the same type. In that respect sequences are like arrays in Java, but with the difference that in Java arrays are objects and in JavaFX Script sequences are not. Elements of a sequence always start from the zeroth index and end at sizeof the sequence minus 1. Elements of the sequence can be defined explicitly in the declaration statement by enclosing them within square brackets ([ ] ), or they can be inserted into the sequence dynamically using the insert keyword with the before and after keywords to specify a desired position. Likewise, elements of a sequence can be deleted using the delete keyword. Range expressions can be used to create a sequence. Sequence slicing provides access to portions (subsets) of a sequence. Predicates are Boolean expressions used to create a new sequence that is a subset of an existing sequence. A sequence can be reversed using the reverse keyword. Either a single element of the sequence or the whole sequence can be bound to a variable or to a sequence. Finally, the Javafx.util.Sequence class contains various functions for manipulating sequences.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset