Built-ins for sequences

chunk

expr?chunk(number-expr)
expr?chunk(number-expr, string expr)

Splits a sequence into multiple sequences of the size given with the first parameter to the built-in (for example, mySeq?chunk(3)). The result is the sequence of these sequences. The last sequence might be shorter than the given size, unless the second parameter is given (for example, mySeq?chunk(3, '-')), that is the item used to make up the size of the last sequence to the given size.

For example:

<#assign seq = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']>
 
<#list seq?chunk(4) as row>
  <#list row as cell>${cell} </#list>
</#list>
 
<#list seq?chunk(4, '-') as row>
  <#list row as cell>${cell} </#list>
</#list>  

produces this output:

  a b c d 
  e f g h 
  i j 
 
  a b c d 
  e f g h 
  i j - - 

This built in is used mostly for outputting sequences in tabular/columnar format. When used with HTML tables, the second parameter is often "\xA0" (that is the code of the no-break space character, also known as nbsp), so the border of the empty TDs will not be missing.

The first parameter must be a number that is at least 1. If the number is not an integer, it will be rounded down to integer (i.e. both 3.1 and 3.9 will be rounded to 3). The second parameter can be of any type and value.

first

expr?first

Returns the first sub-variable of the sequence.

If the sequence is empty, an error occurs that terminates template processing.

join

expr?join(separator-expr
or
expr?join(separator-expr, last-separator-expr)
or
expr?join(separator-expr, last-separator-expr, when-empty-expr)
or
expr?join(separator-expr, last-separator-expr, when-empty-expr, after-last-expr)

Joins a sequence into a string by using a string separator. Optionally, you can include an additional separator between the next-to-last and last elements, plus an additional argument to use when the sequence has no elements, as well as a suffix to add after the last element has been appended.

Example 1: Join a list with a separator:

${["a", "b", 1]?join(",")}

produces this output:

a,b,1

Note that the number one was forcibly transformed to a string.

Example 2: Join a list with two separators:

<#assign list=["red", "blue", "cyan"]>
The colors are ${list?join(", ", " and ")}

produces this output:

The colors are red, blue and cyan

Example 3: Join a list with separators and an optional empty string:

<#assign list=["red", "blue", "cyan"]>
The colors are ${list?join(", ", ", ", "empty")}
<#assign list=[]>
The colors are ${list?join(", ", ", ", "empty")}

produces this output:

The colors are red, blue, cyan
The colors are empty

Example 4: Join a list with an optional empty string and an optional suffix

<#assign list=["red", "blue", "cyan"]>
The colors are ${list?join(", ", ", ", "empty", " - " + list?size?string)}
<#assign list=[]>
The colors are ${list?join(", ", ", ", "empty", " - " + list?size?string)}

produces this output:

The colors are red, blue, cyan - 3
The colors are empty

The optional suffix is appended only if the item had any elements, as in the first assignment. The suffix is composed of a separator (" – ") plus the list size, in string format. Note that the size is converted to a string to enable the concatenation. Otherwise, RPL would have attempted to add a string with a number, which would result in an error.

last

expr?last

Returns the last sub-variable of the sequence.

If the sequence is empty, an error occurs that terminates template processing.

reverse

expr?reverse

Returns the sequence in reversed order.

seq_contains

expr?seq_contains(expr)

Determines whether the sequence contains the specified value.

The built- in has one parameter, the value to find.

NOTE: The seq_ prefix is required in the built-in name to differentiate it from the contains built-in that searches a substring in a string (since a variable can be both a string and a sequence on the same time).

Example:

<#assign x = ["red", 16, "blue", "cyan"]>
"blue": ${x?seq_contains("blue")?string("yes", "no")}
"yellow": ${x?seq_contains("yellow")?string("yes", "no")}
16: ${x?seq_contains(16)?string("yes", "no")}
"16": ${x?seq_contains("16")?string("yes", "no")}  

produces this output:

"blue": yes
"yellow": no
16: yes
"16": no  

To find the value, the built-in uses RPL's comparison rules (as if you were using the == operator). The difference is that comparing two values of different types or of types for which RPL does not support will not cause an error; instead, the values will be evaluated as not equal. Thus, you can use this built-in to find only scalar values (i.e. string, number, boolean or date/time values). For other types, the result will always be false.

For fault tolerance, this built-in also works with collections.

seq_index_of

exp?seq_index_of(expr)
exp?seq_index_of(expr, index-expr)

Returns the index of the first occurrence of a value in the sequence, or -1 if the sequence does not contain the specified value. The value to find is specified as the first parameter.

Optionally, you can specify the index where the searching should begin as a second parameter. This might be useful if the same item can occur multiple times in the same sequence. There is no restriction on the numerical value of the second parameter: if the value is negative, it evaluates to zero; if it is greater than the length of the sequence, it evaluates to the length of the sequence. Decimal values will be truncated to integers.

To find the value, the built-in uses RPL's comparison rules (as if you were using == operator). The difference is that using this built-in, comparing two values of different or unsupported types will not cause an error; instead, the values will be evaluated as not equal. Thus, you can use it only to find scalar values (i.e. string, number, boolean or date/time values). For other types of values, the result will always be -1.

NOTE: seq_ prefix is required in the built-in name to differentiate it from the index_of built-in that searches a substring in a string, since a variable can be both a string and a sequence at the same time.

Example:

<#assign colors = ["red", "green", "blue"]>
${colors?seq_index_of("blue")}
${colors?seq_index_of("red")}
${colors?seq_index_of("purple")}  

produces this output:

2
0
-1  

Example:

<#assign names = ["Joe", "Fred", "Joe", "Susan"]>
No 2nd param: ${names?seq_index_of("Joe")}
-2: ${names?seq_index_of("Joe", -2)}
-1: ${names?seq_index_of("Joe", -1)}
 0: ${names?seq_index_of("Joe", 0)}
 1: ${names?seq_index_of("Joe", 1)}
 2: ${names?seq_index_of("Joe", 2)}
 3: ${names?seq_index_of("Joe", 3)}
 4: ${names?seq_index_of("Joe", 4)}  

produces this output:

No 2nd param: 0
-2: 0
-1: 0
 0: 0
 1: 2
 2: 2
 3: -1
 4: -1  

seq_last_index_of

expr?seq_last_index_of(expr)
expr?seq_last_index_of(expr, index-expr)

Returns the index of the last occurrence of a value in the sequence, or -1 if the sequence does not contain the specified value. This built-in is the same as seq_index_of, except that it searches backward, starting from the last item of the sequence.

Optionally, you can specify the index where the searching should begin as a second parameter. This might be useful if the same item can occur multiple times in the same sequence. There is no restriction on the numerical value of the second parameter: if the value is negative, it evaluates to zero; if it is greater than the length of the sequence, it evaluates to the length of the sequence. Decimal values will be truncated to integers.

NOTE: The seq_ prefix is required in the built-in name to differentiate it from the last_index_of built-in that searches for a substring in a string (since a variable can be both string and sequence at the same time).

For example:

<#assign names = ["Joe", "Fred", "Joe", "Susan"]>
No 2nd param: ${names?seq_last_index_of("Joe")}
-2: ${names?seq_last_index_of("Joe", -2)}
-1: ${names?seq_last_index_of("Joe", -1)}
 0: ${names?seq_last_index_of("Joe", 0)}
 1: ${names?seq_last_index_of("Joe", 1)}
 2: ${names?seq_last_index_of("Joe", 2)}
 3: ${names?seq_last_index_of("Joe", 3)}
 4: ${names?seq_last_index_of("Joe", 4)}  

produces this output:

No 2nd param: 2
-2: -1
-1: -1
 0: 0
 1: 0
 2: 2
 3: 2
 4: 2  

size

expr?size

Returns the number of sub-variables in sequence as a numerical value. The highest possible index in a sequence is s?size - 1 (since the index of the first sub-variable is 0) assuming that the sequence has at least one sub-variable.

sort

expr?sort

Returns the sequence sorted in ascending order.

To sort in descending order, use this built-in, then the reverse built in.

This built-in works only if all sub-variables are of the same type. If the sub-variables are strings, it uses locale (language) specific lexical sorting (which is usually not case sensitive).

Example:

<#assign ls = ["whale", "Barbara", "zeppelin", "aardvark", "beetroot"]?sort>
<#list ls as i>${i} </#list>  

produces this output with the US locale:

aardvark Barbara beetroot whale zeppelin  

sort_by

expr?sort_by(key-expr)

Returns the sequence of hashes sorted by the given hash sub-variable in ascending order.

To sort in descending order, use this built-in, then the reverse built in.

The rules are the same as with the sort built-in, except that the sub-variables of the sequence must be hashes, and you must give the name of a hash sub-variable

that will determine the order.

For example:

<#assign ls = [
  {"name":"whale", "weight":2000},
  {"name":"Barbara", "weight":53},
  {"name":"zeppelin", "weight":-200},
  {"name":"aardvark", "weight":30},
  {"name":"beetroot", "weight":0.3}
]>
Order by name:
<#list ls?sort_by("name") as i>
- ${i.name}: ${i.weight}
</#list>
 
Order by weight:
<#list ls?sort_by("weight") as i>
- ${i.name}: ${i.weight}
</#list>  

produces this output with the US locale:

Order by name:
- aardvark: 30
- Barbara: 53
- beetroot: 0.3
- whale: 2000
- zeppelin: -200
 
Order by weight:
- zeppelin: -200
- beetroot: 0.3
- aardvark: 30
- Barbara: 53
- whale: 2000  

If the sub-variable you want to use for the sorting is nested at a deeper level (that is, if it is a sub-variable of a sub-variable),  you can use a sequence as a parameter that specifies the names of the sub-variables that lead down to the desired sub-variable. For example:

<#assign members = [
    {"name": {"first": "Joe", "last": "Smith"}, "age": 40},
    {"name": {"first": "Fred", "last": "Crooger"}, "age": 35},
    {"name": {"first": "Amanda", "last": "Fox"}, "age": 25}]>
Sorted by name.last: 
<#list members?sort_by(['name', 'last']) as m>
- ${m.name.last}, ${m.name.first}: ${m.age} years old
</#list>  

produces this output with the US locale:

Sorted by name.last: 
- Crooger, Fred: 35 years old
- Fox, Amanda: 25 years old
- Smith, Joe: 40 years old  

unique

Returns a new sequence where the elements are unique.