LIST

<< Click to Display Table of Contents >>

Navigation:  Gekko User Manual > Gekko statements >

LIST

Previous pageReturn to chapter overviewNext page

A Gekko list contains sequentially ordered variables (elements) of any type. List names always start with the symbol #, like the other collection types map and matrix. You may refer to list elements by means of indexes, for instance #m[1] for the first element of #m. Listfiles can be used, using for instance #(listfile m) instead of #m, where the list elements are stored in the external file m.lst instead of in a databank.

 

Guide: lists

For an easier introductory guide on Gekko lists, see this page.

 

Upgrade note

Gekko 2.x uses syntax like list = a, #m1, d, #m2;, which in Gekko 3.x would be #= a, {#m1}, d, {#m2}; (the string 'a' plus the strings inside #m1, etc.).

 

Scrape data from xls(x) spreadsheets

See SHEET<import> to see how to load a spreadsheet as a nested list of "cells" and scrape data from these with loops.

 

A general list is defined with parentheses and commas, for instance #= ('a', 120, 2020q3);. In that case, the list contains a string, a value, and a date. In the special case where all the list elements are simple alphanumeric words (including '_') without special characters, you may use for instance #= a, a38, 7z, 5, 007, 2001q1; instead of the more cumbersome #= ('a', 'a38', '7z', '5', '007', '2001q1');. The 'naked' version without parentheses and quotes is practical for lists of names etc. If all the list elements are values, like #= 1, 2, 3;, a list of values is produced instead of a list of strings (among other things, this is practical regarding the series statement, for instance = 1, 2, 3;). A naked list either returns a list of strings or a list of values, cf. the page on naked lists.

 

You may may use the operators += and -= to add or subtract elements from a list (this works for naked lists, too: #= a, b; #+= c, d; #-= c, d;). If you need to use a naked list with one element, use a trailing comma, for instance #= a,;. This way, you can easily add or remove a single element like this: #= a, b; #+= c,; #-= c,;. Single-item lists (so-called singletons) can alternatively be stated as #= list('a') or #= ('a',). Using #= a or #= ('a') will fail with an error, since Gekko understands this as setting a list equal to a series or a string. An empty list can be created with #= list().

 

The first element of a list #m is #m[1], and the last element is #m[#m.length()]. Slices/sublists can be cut out by means of ranges, for instance #m[2..5]. Non-naked lists may contain any other variable types, including lists, so #= (1, (2, 3)); is a nested/reursive list, where #m[2][1] would refer to 2 (because #m[2] refers to the sublist (2, 3)).

 


 

Syntax

 

#name = ( expr1 REP n1 , expr2 REP n2, ... ); //REP repeats the item
#name = name, name, ... ;                     //short form for 2 or more string variables
#(listfile m1) = #(listfile m2);             //use of listfiles m1.lst and m2.lst (for lists of scalars, or nested lists of scalars)
#name = list(...);                           //useful for singleton lists or empty lists like #m = list('a') or #m = list().
list #name = ...;                             //list keyword may be added, but is typically not necessary.
list ?;                                       //show/count lists in open databanks

 

It is no longer legal to use for instance list m = ... ;, omitting the # on the left-hand side.

 

Referring:

 

{#m}               //use braces {...} to use strings as variable names.

 

 

You may pick out individual items from a list with the []-brackets. For instance:

 

#x[%i] = element number %i (a scalar)

#x[%i1..%i2] = elements %i1 to %i2 (inclusive), returns a list (slice)

#x[%i1..%i2, %j1..%j2] = matrix-like selection of nested list

#x[%i1..%i2][%j1..%j2] = beware that this is different from above (nested indexing).

#x['fx*'] = returns a list of those string elements that start with 'fx'

#x['f?a'] = strings that match the pattern 'f?a'

#x['pxa'..'pxqz'] = strings in the range 'pxa' to 'pxqz' (both inclusive)

#x['a'] = check if the string 'a' is an element in the non-nested list #x.

#x['a', 'b'] = check if the list ('a', 'b') is a sublist in the nested list #x. ALso works for more dimensions.

 

Use #x.length() or length(#x) to get the number of elements in #x, #x[0] cannot be used for this anymore. In IF statements and $-conditions, you can use the syntax if(#x['a'] == 1) or if('a' in #x) to condition on #x containing some particular element.

 

Operators:

 

#= #x1 + #x2;. Same as #= #x1.extend(#x2);. Adds the elements of #x2 to #x1, use of += is possible. Note that #x1 + %s is not legal (where for instance #x1 is a list of strings and %s is a string): to append to each list item, use #x1.suffix(%s) instead.

#= #x1 - #x2;. Same as #= #x1.except(#x2);. Subtracts the elements of #x2 from #x1. Use of -= is possible.

#= #x1 || #x2;. Same as #= #x1.union(#x2);. Union of two lists, dublets removed.

#= #x1 && #x2;. Same as #= #x1.intersect(#x2);. Intersection of two lists.

 

In order to generate sequences you can use the function seq(), for instance #= seq(1, 100); produces a list of values 1, 2, ... , 100, and that #= seq(1, 100).strings(); produces a corresponding list of strings '1', '2', ... '100'.

 

The LIST keyword is optional and can typically be omitted. Use rep to repeat items. For the last item, when defining or calculating timeseries, you may use rep *. You may use a list definition with parentheses (strict version) everywhere a variable or expression is expected.

 

There are quite a lot of functions to deal with string lists, for instance sort() to sort elements, unique() to remove dublets, prefix()/suffix() to add prefixes/suffixes to elements, etc. You can also use the union(), except(), and intersect() functions for lists of strings, or equivalently via operators ||, -, and &&. Please see the examples below, and the functions section. Regarding string lists of variable names, there are a lot of functions to handle banks, frequencies, indexes, etc., cf. the functions section, under 'Bank/name/frequency/index manipulations'.

 

A listname always starts with the symbol '#', like the other collection types map and matrix. If you prefer to refer to a list item by name instead of numbers/indexes, see the MAP collection. In that case, you could use for instance #m['nairu'] or #m.nairu rather than for instance #m[1] to refer to a particular named object in the collection (this makes the programs easier to read).

 

String lists with variable names, optionally including banks, frequencies, indexes, etc. are often used, and to refer to the variables themselves, {}-curlies must be used. For instance: #= ('x', 'b2:y!m[a, u]', '%z'); contains the strings corresponding to x (series x without bank indication, and with default frequency), monthly array series y from bank b2 with indexes [a, u], and finally a scalar %z. If you want to refer to the variables corresponding to these strings, use {}-curlies, for instance PRINT {#m};. This is the same as PRINT x, b2:y!m[a, u], %z;.

 

Lists of values are often used, for instance to define series. A list of values could be #= 1, 2, 3;, omitting the parentheses. If you need to use the sequential data in linear algebra, instead of #= 1, 2, 3; or #= (1, 2, 3); you may use a row or column vector instead, for instance #= [1, 2, 3]; or #= [1; 2; 3];. The latter column vector is a bit more similar to the list in the sense that #m[1], #m[2] is allowed regarding column vectors, where row vectors would have to use #m[1, 1], #m[1, 2], etc. If a list of values is given as mathematical expressions, you must use enclosing parentheses, for instance #= (1/7, 2 + %v, 3*%v);.

 

All Gekko functions implement so-called UFCS so that a function like for instance extend(#x, #y) can generally be written as #x.extend(#y). This makes chaining of such function calls more readable, for instance #= #m1.extend(#m2).except(#m3).

 

 

 

 

List functions:

 

Note that some of the functions assume that the lists are lists of strings. This will be fixed regarding values and dates.

 

Function name

Description

Examples

[x]-index

Index: picks out a single element. In contrast to R, this does not return a 1-element list containing the variable. If you need that, use for instance #m[3..3].

Returns: var

#m[3];  //the third element

[x1..x2]-index

Index: picks out a range of elements. You may omit x1 or x2.

Returns: list

#m[3..5];  //the third to fifth elements

[x1, x2]-index

For a nested list of lists, #m[3, 5] will return the same element as #m[3][5], so this is just convenience to make a nested list accessible like a matrix. See more here.

Returns: variable

 

[New in 3.0.6].

#= ((1, 2), (3, 4));
prt #m[2, 1], #m[2][1];  //same

[x1..y1, x2..y2]-index

[x1..y1, x2]-index

[x1, x2..y2]-index

For a nested list of lists, #m[2..3, 2..4] will select the given 'rows" and "columns", corresponding to selecting a submatrix from a matrix. Beware that in general, #m[2..3, 2..4] is completely different from #m[2..3][2..4].  See more here.

Returns: list

[New in 3.0.6].

//  1  2  3
//  4  5  6
//  7  8  9
// 10 11 12
#= ((1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12));
prt #m[2, 2..3];
prt #m[2][2..3]; //same as above
prt #m[2..4, 2]; //matrix-like selection
prt #m[2..4][2]; //different from above!
prt #m[2..4, 2..3]; //matrix-like selection
prt #m[2..4][2..3]; //different from above!

 

 

 

append(x1, x2)

append(x1, i, x2)

Adds variable x2 as it is at the end of list x1. Note that if x2 is a list of for instance 3 items, only 1 element is added (the list itself). If you need to add the 3 elements individually, use extend().

 

If used with i argument, x2 is inserted at index i, instead of at the end. See also extend().

 

To prepend, use append(x1, 1, x2).

 

Returns: list

#= #x1.append(#x2);  //or: append(#x1, #x2)
#= #x1.append(2, #x2);  //insert at position 2

contains(x1, x2)

Checks if the list of strings x1 contains the string x2. Returns 1 if true, 0 otherwise. You may alternatively use x2 in x1, see the last example. See also the count() and index() functions. The comparisons are case-insensitive.

Returns: val

%= #x1.contains(%s);
if(#x1.contains(%s) == 1); tell 'yes'; end;
if(%s in #x1); tell 'yes'; end;

count(x1, x2)

Counts the number of times the string x2 is present in the list of strings x1. See also the contains() and index() functions.

 

 

Note: to obtain the number of elements in a list, use the length() function. The comparisons are case-insensitive.

 

Returns: val

%= #x1.count(%s);  //or: count(#x1, %s)

data(x)

Accepts a string of blank-separated values x and turns them into a list of values. This is handy for long sequences of blank-separated numbers, instead of manually setting the commas.

Returns: list

#= data('1.0  2.0  1.5');

dates(x)

Tries to convert each element of the list x to a date.

Returns: list

#= dates(#x);

except(x1, x2)

 

clip0051

The except() function subtracts x2 from x1. You may alternatively use the operator -. Only works for lists of strings. See also intersect() and union().

 

Was called difference() in Gekko 2.0. See also extend().

 

Returns: list

#= #x1.except(#x2);  //or: except(#x1, #x2)
#= #x1 - #x2;        //same
 
#-= #x1;  //subtract from itself

extend(x1, x2)

extend(x1, i, x2)

The arguments x1 and x2 must be lists. The function inserts the elements of list x2 one by one at the end of (or at position i in) the list x1. The resulting list may contain dublets.

 

For two lists x1 and x2, you may alternatively use the + operator. See also except() and append().

 

To pre-extend, use extend(x1, 1, x2).

 

Returns: list

#= #x1.extend(#x2);  //or: extend(#x1, #x2)
#= #x1 + #x2; //same as above
#= #x1.extend(2, #x2);  //insert at position 2
 
#+= #x1; //add to itself

flatten(x)

For at list x, the function returns a flattened version of the list. For instance, the list (1, (2, 3)) is transformed into a non-recursive list of non-list elements: (1, 2, 3).

 

Returns: list

 

#m1 = (1, (2, 3));
#m2 = #m1.flatten(); //or: flatten(#m1).

index(x1, x2)

Returns the index of the first occurrence of the string x2 in the list of strings x1. Returns 0 if x2 is not found in x1. See also the count() and contains() functions. The comparisons are case-insensitive.

Returns: val

%= #x1.index(%s);  //or: index(#x1, %s)

intersect(x1, x2)

 

clip0050

The intersect() function finds the common elements of the two list of strings x1 and x2. The resulting list will not contain dublets. You may alternatively use the operator &&. Only works for lists of strings. See also except() and union().

Returns: list

#= #x1.intersect(#x2);  //or: intersect(#x1, #x2)
#= #x1 && #x2;

length(x)

Returns the number of elements in the list x. You may use len() instead of length().

Returns: val

%= #x.length();  //or: length(#x).
%= #x.len(); //the same

list(x1, x2, ...)

Returns a list of the variables x1, x2, etc. The function is handy for lists with only 0 or 1 elements. See examples.

Returns: list

#= ();      //will fail
#= list();  //ok: empty list

#= (1, 2);  //easy
#= (1);     //will fail
#= (1,);    //is ok
#= list(1); //is ok

lower(x)

Returns string elements in the list as lower-case.

Returns: list

#= #x1.lower();  //or: lower(#x1)

pop(x1, i)

pop(x1)

Removes the element at position i in the list x1. Removes the last element if called with pop(x).

Returns: list

#= #x1.pop(2);  //or: pop(#x1, 2)
#= #x1.pop();  //last element
#= #x1.pop(1);  //first element

preextend(x1, x2)

Same as extend(x1, 1, x2), putting the elements of x2 in the first position of x1.

#= #x1.preextend(#x2);  //insert at position 1

prefix(x1, x2)

If x1 is a list of strings, each element has the string x2 prefixed (prepended)

Returns: list

#= #x1.prefix(%s);  //or: prefix(#x1, %s);

prepend(x1, x2)

Same as append(x1, 1, x2), putting x2 in the first position of x1.

#= #x1.prepend(#x2);  //insert at position 1

sort(x)

sort(x, 'natural')

Returns a sorted list of strings, provided that x is a list of strings. Sorting is case-insensitive.

When the 'natural' argument is used, strings containing numbers will sort naturally, for instance returning a8, a9, a10, instead of a10, a8, a9.

Returns: list

Natural sort: [New in 3.1.10].

#= #x.sort();  //or: sort(#x)
#= #x.sort('natural');

remove(x1, x2)

Removes any string x2 from the list of strings x1. See also the except() function.

Returns: list

#= #x1.remove(%s);  //or: remove(#x1, %s);

#= #x1 - %s;        //also legal

replace(x1, x2, x3)

replaceinside(x1, x2, x3)

replaceinside(x1, x2, x3, max)

replace(): In the list of strings x1, if this string element is the same as x2, x3 is inserted instead.

 

replaceinside(): the string element has any occurences of x2 inside the string replaced with x3. The replacements may be limited via the max argument.

 

Returns: list

#= #x1.replace(%x2, %x3); //or: replace(#x1, %x2, %x3)
 
#= #x1.replaceinside(%x2, %x3); //or: replace(#x1, %x2, %x3, 'inside')

reverse(x)

To be done


split(x, s)

To be done


strings(x)

Tries to convert each element of the list x to a string

Returns: list

#= strings(#x);

suffix(x1, x2)

If x1 is a list of strings, each element has the string x2 suffixed (appended)

Returns: list

#= #x1.suffix(%s);  //or: suffix(#x1, %s);

t(x)

For a nested list of lists, the t() function returns the transpose, similar to transposing a matrix. [New in 3.0.6].

Returns: list (of lists)

#= ((1, 2), (3, 4));
#m, t(#m);

union(x1, x2)

 

clip0049

The union() function finds the union of the two lists. Alternatively use the operator ||. The resulting list will not introduce dublets, in contrast to the similar + operator (simple concatenation). Only works for lists of strings. See also except() and intersect().

Returns: list

#= #x1.union(#x2);  //or: union(#x1, #x2)
#= #x1 || #x2;

unique(x1)

Retains only those elements of list x1 that are unique (list of strings only).

Returns: list

#= #x1.unique();  //or: unique(#x1)

upper(x)

Returns string elements in the list as upper-case.

Returns: list

#= #x1.upper();  //or: upper(#x1)

vals(x)

Tries to convert each element of the list x to a value

Returns: list

#= vals(#x);

venn(x1, x2)

 

 

For two lists of strings, this function prints out lists corresponding to a Venn diagram.

 

clip0150

 

That is, intersection and two differences. For instance, venn(#m1, #m2) corresponds to printing out the following:

 

#m1 && #m2

#m1 - #m2

#m2 - #m1

 

See also intercept(), except() and union().

Returns: nothing.

#m1 = a, b, c, d, e;
#m2 = c, d, e, f, g;
venn(#m1, #m2);
 

//Results:

 
//The following 3 strings are in both lists:
//'c', 'd', 'e'
 
//The following 2 strings are in list #1, but not in list #2:
//'a', 'b'
 
//The following 2 strings are in list #2, but not in list #1:
//'f', 'g'

 

 

A string (or list of strings) representing variable names may be manipulated by means of Gekko's inbuilt functions to handle these. Variable names here include bank, frequency, indexes, etc., and examples of such functions could be setBank(), removeBank(), replaceBank(), setFreq(), removeFreq(), setNamePrefix(), etc. There are many more of such functions, see the functions section, under ‘Bank/name/frequency/index manipulations’.

 

For instance, if you have a list #= ('x', 'y');, you may use prt {#m}; to print out x and y, prt {#m.setBank('b')}; to print out b:x and b:y, or prt {#m.setFreq('q')}; to print out x!q and y!q (here, prt b:{#m}; and prt {#m}!q; will work, too).

 

 


 

Examples

 

Define a list:

 

#= ('a', 'b', 'c');            //list of strings
#= a, b, c;                    //naked list syntax, only allowed for a list of simple names.
#+= d, e;                      //naked list adding two elements.
#-= d, e;                      //naked list removing them again
#+= d,;                        //naked list adding one element, note the comma
#-= d,;                        //naked list removing it again, note the comma
#= x, y;
#= x[a], x[#i];                //naked list allows indexes too (#i is a list of strings)
#+= #m2;                       //adding another list
#= 1, 3, 2;                    //list of simple numbers, parentheses can be omitted
#= (2020q1, 2020q4, 2021q1);   //list of dates
#= (a, b, c);                  //NOTE: this is a list of series objects, not strings!
#= (('a', 'b'), (1, 3));       //list of lists
#= seq(1, 3).strings();        //the strings '1', '2' and '3'

 

If instead of for instance d, e, etc. above you need to use strings like %s1 or %s2, you may use for instance #+= {%s1}, {%s2}; or #+= {%s},;.

 

As shown, for naked lists you may use indexes to state array-series, for instance x[#i] is unfolded into x[a], x[b], x[c], if #= a, b, c. In the last list, #m[1] refers to the list ('a', 'b'), #m[2] refers to the list (1, 3), and for instance #m[1][2] refers to 'b'. To print a list, simply use prt #m;. If the list is a list of strings, and you want to print the variables corresponding to the strings, use {}-curlies:

 

#= ('a', 'b', 'c');            //list of strings, or: #m = a, b, c;
prt #m;                          //print the raw strings
prt {#m};                        //print the variables (series) a, b, and c. Same as "prt a, b, c;".

 

There are two functions to add items to a list: append() and extend():

 

#m1 = (1, 2, 3);                 //or: #m = 1, 2, 3;
#m2 = (4, 5);
#= #m1.append(#m2);            //result: (1, 2, 3, (4, 5)), nested list
#= #m1.extend(#m2);            //result: (1, 2, 3, 4, 5)

 

Gekko functions implement so-called UFCS, so the function append(#m1, #m2) may alternatively be written #m1.append(#m2), moving the first argument of the original function out of the parentheses. This provides a more fluent interface, and enables easy chaining of list functions (see examples below). As it is seen, append() puts the list #m at position 4 in #m1, whereas extend() unpacks #m2 and puts the two elements at positions 4 and 5 in #m1. Therefore, if you need to add a single value to a list, use append(), but if you need to add the elements of a list to another list, use extend():

 

#m1 = (1, 2, 3);
#= #m1.append(4);              //result: (1, 2, 3, 4)
#= #m1.extend(4);              //Fails with an error

   

Instead of #m1.extend(#m2), the + operator can be used instead of extend() when dealing with two lists:

 

#m1 = (1, 2, 3);
#m2 = (4, 5);
#= #m1 + #m2;                  //result: (1, 2, 3, 4, 5), same as #m1.extend(#m2)

 

It should be noted that #m1 + %s does not append %s to the list (but will fail with an error). Use #m1.append(%s) or #m1 + list(%s) instead. In earlier Gekko versions, the expression #m1 + %s appended %s to each element of #m1, but this behavior is deprecated.

 

Lists in Gekko may contain dublets. Still, set operations are possible with the functions union(), except() and intersect():

 

#m1 = ('a', 'b', 'c');               //or: #m1 = a, b, c;
#m2 = ('b', 'd');
#= #m1.union(#m2);                 //result: ('a', 'b', 'c', 'd')
#= #m1.except(#m2);                //result: ('a', 'c')
#= #m1.intersect(#m2);             //result: ('b')

 

It is noted that union() avoids introducing dublets in the list, which is not the case regarding extend() and the + operator. Instead of these functions, you may use operators ||, - and &&:

 

#m1 = ('a', 'b', 'c');               //or: #m1 = a, b, c;
#m2 = ('b', 'd');
#= #m1 || #m2;                     //result: ('a', 'b', 'c', 'd')
#= #m1 - #m2;                      //result: ('a', 'c')
#= #m1 && #m2;                     //result: ('b')

 

If the list #x1 contains none of the #x2 elements, the expression #x1 + #x2 - #x2 will be = #x1. However, Gekko lists may contain dublets, and you can use the unique() function to remove these, and the sort() function for sorting. For instance:

 

#m1 = ('c', 'b', 'a');                   //or: #m1 = c, b, a;
#m2 = ('b', 'c', 'd', 'e');
#= #m1.extend(#m2);                    //result: ('c', 'b', 'a', 'b', 'c', 'd', 'e' )
#= #m1.extend(#m2).unique();           //result: ('c', 'b', 'a', 'd', 'e')
#= #m1.extend(#m2).unique().sort();    //result: ('a', 'b', 'c', 'd', 'e')

 

The above example also illustrates function chaining. The expression #m1.extend(#m2).unique().sort() is easier to understand than the equivalent but more backwards expression sort(unique(extend(#m1, #m2)).

 

To check if a list contains an item, use contains() or index():

 

#= ('a', 'b', 'c');                    //or: #m = a, b, c;
%= #m1.contains('b');                  //result: 1 (true)
%= #m1.index('b');                     //result: 2 (the position)

 

You may replace elements in a list, for instance:

 

#m1 = ('ax', 'bx', 'xc');                    //or: #m1 = ax, bx, xc;
#= #m1.replace('bx', 'y')                  //result: ('ax', 'y', 'xc')
#= #m1.replaceinside('x', 'z')             //result: ('az', 'bz', 'zc')

 

The last function, replaceinside(), replaces text inside the individual elements.

 

List elements may be of mixed types, for instance (1, 'two', 2003q3), and lists of values are often used to feed values into timeseries:

 

time 2020 2026;
= 100, 101 rep 3, 102, 103 rep *;        //parentheses can be omitted for simple values

prt x;                                     //result: 100, 101, 101, 101, 102, 103, 103

                                   

You can use rep to repeat values, and rep *  is special when used to define a series, since it repeats the last item to make the list fit with the sample (here: 7 observations). If you have input data with (a lot of) blank-separated values, you may use the data() function instead of manually setting the commas:

 

time 2020 2026;
= data('100 101 101 101 102 103 103');    //result: 100, 101, 101, 101, 102, 103, 103

                                   

Lists can be looped, for instance:

 

#= ('a', 'b', 'c');                       //or: #m = a, b, c
%= '';
for string %= #m;
  %+= %i;
end;
prt %s;                                     //result: 'abc'

 

Lists can be nested, for instance an #alias list (cf. OPTION interface alias):

 

= 100; 
= series(1); y[z] = 200;
option interface alias = yes;
global:#alias = (('a', 'x'), ('b', 'y[z]'));
prt a, b; //will be the same as prt x, y[z]

 

An #alias list can among other things be convenient as a bridge between the naming conventions of two different models.

 

Listfiles

 

Instead of storing lists in a databank, you may optionally use an external file instead. Using a listfile animals.lst (you may use edit animals.lst; to do this):

 

------------ animals.lst ------
//comments like these are allowed, and blank lines too
dog
cat
mouse
fish
------------------------------

 

You can use the listfile in the following way:

 

#animals = #(listfile animals);

 

Listfiles may contain strings or values, and for simple strings starting with a letter, you may omit single quotes. If you need to make sure that an element is interpreted as a string and not as a value, you can enclose the string in single quotes.

 

When Gekko reads an element, if it is enclosed in quotes, it always becomes a string. Otherwise, the interpretation rules are the same as for naked lists. When writing elements, if all elements are simple strings starting with a letter, Gekko will omit the quotes. Else it will write strings with single quotes, and dates are written as strings, too. To convert a list of strings into a list of dates, just use the dates() function. Like normal lists, listfiles may contain elements beginning with '-',for instance:

 

------------ items.lst -------
x1
-x2
x3
------------------------------

 

But you cannot put complicated items like expressions into a listfile (use a normal list for that). You can create a listfile m.lst with #(listfile m) = a, b, c;. Nested listfiles are possible: just separate the elements with the ';' symbol:

 

------------ nested.lst ------
1
2; 3
mouse
2010q1; 2010q3
------------------------------

 

All these items are converted into strings, because they are not all values. You could create this file with #(listfile nested) = ('1', ('2', '3'), 'mouse', ('2010q1', '2010q3')). The last element can be followed by the ';' symbol, but it may also be omitted. The following list is similar to a matrix:

 

------------ matrix.lst ------
1; 2
3; 4
------------------------------

 

If #= #(listfile matrix), for instance #m[2][1] = 3, corresponding to row 2, column 1. This is similar to the matrix #= [1, 2; 3, 4], where #m[2, 1] = 3. In general, the listfile format corresponds to .csv, and the reason ',' is not used to delimit elements is that csv files may allow numbers to be stored with decimal separator ',' instead of '.'.

 

Instead of using a two-dimensional csv-like listfile like matrix.lst above, you may instead store such data in an Excel spreadsheet, and load them with sheet <import list> #m file = ... ;.

 

 

Searching

 

You may search a list of strings using wildcards, in order to return certain patterns of string elements.

 

#m1 = ('abd', 'abcd', 'abcde');           //or: #m = abd, abcd, abcde
#m2 = #m1['a*d'];                         //result: 'abd', 'abcd'
#m3 = #m1['a?d'];                         //result: 'abd'
#m4 = #m1.addbank('b1').addfreq('q');     //result: 'b1:abd!q', 'b1:abcd!q', 'b1:abcde!q'

 

As the last line shows, there are a lot of functions available, if you need to handle for instance banknames, frequency indicators, etc. on such lists of names. See under functions, bank/name/frequency/index manipulations. Note that if you need to for instance print the elements of #m1 with a particular bank and frequency, you may use either prt {#m1.addbank('b1').addfreq('q')};, or the easier prt b1:{#m1}!q;.

 

You may use a 'naked' wildcard to obtain variable names from open databanks, for instance:

 

abd = 1; abcd = 2; abcde = 3;
#m2 = ['a*d'];                            //result: 'abcd', 'abd', list is alphabetical            
#m3 = ['a?d'];                            //result: 'abd'

 

The wildcards match variable names found in open databanks. Please keep in mind that the logic regarding such 'naked' wildcards is a bit different from searching inside a list of strings. A wildcard like ['a*d'] will look for series starting with 'a' and ending with 'd', but only in the current first-position databank, and only regarding variables with the same frequency as the current frequency. To get series names from all banks with all frequencies, starting with 'a' and ending with 'd', you would have to use ['*:a*d!*']. And to get, for instance variables starting with % (scalars), and then followed by 'a' and ending with 'd', you would have to use ['%a*d']. See more on the wildcards page and on INDEX section.

 

To print out results of wildcards searches, {}-curlies must be used, for instance:

 

abd = 1; abcd = 2; abcde = 3;
prt ['a*d'];                              //prints the two strings 'abcd' and 'abd'
prt {['a*d']};                            //result: same as prt abcd, abd;
prt {'a*d'};                              //shortcut: the inner []-brackets may be omitted here

 

As seen above, you must use {}-curlies to print out the variables corresponding to a wildcard search. And as shown, you do not have to use the pattern {['....']}, but can omit the innermost []-brackets and just use {'....'} to print wildcard variables.

 

 


 

Lists and array-series

 

As a last note, lists can be used to define domains for array-series. See the SERIES section, but the following example illustrates the use:

 

time 2020 2022;
= series(1);                                                          //array-series with 1 dimension
x[a] = 1; x[b] = 2; x[c] = 3;
#= a, b, c;
<n> x[#i], sum(#i, x[#i]), sum(#i, x[#i] $ (#i in #i.remove('b')));

 

The result is the following:

 

                                                                    sum(#i, x[#i] 
                                                                 s   $ (#i in #i. 
                 x[a]           x[b]           x[c]  um(#i, x[#i])  remove('b'))) 
  2020         1.0000         2.0000         3.0000         6.0000         4.0000 
  2021         1.0000         2.0000         3.0000         6.0000         4.0000 
  2022         1.0000         2.0000         3.0000         6.0000         4.0000 

 

 

So x[#i] prints out the three elements, sum(#i, x[#i]) sums them up, and sum(#i, x[#i] $ (#i in #i.remove('b'))) show the sum for the list #i except the element 'b'.

 

You may assign a domain to array-series dimensions with the setdomains() function, and you may restrict which elements are printed/plotted via a special #default map. See more in the SERIES section.

 

 


 

Note

 

See the page with syntax diagrams if the basics of names, expressions, etc. is confusing.

 

You can remove <direct> in list<direct> from older Gekko 2.0/2.2/2.4 code.

 

You can use minus (-) before a list item in a naked list. This can for instance be used in the Laspeyres chain index function laspchain(), to indicate a variable that is to be deducted. For instance:

 

#= p1, p2, p3, p4;   //same as: #p = ('p1', 'p2', 'p3', 'p4');
#= x1, x2, -x3, x4;  //same as: #q = ('x1', 'x2', '-x3', 'x4');
#= laspchain(#p, #q, 2010);

 

The function returns a map #m containing the aggregated p and q series as named elements, where series x3 is to be deducted from the aggregation (and the price p is set to 1 in 2010). The resulting series and quantities can be accessed with #m.p and #m.q.

 

If you have input data with blank-separated values, you may use the data() function to avoid having to set the commas, for instance #= data('1.0  2.0  1.5');. This function can be practical for long lists of numbers. Data from an Excel spreadsheet can be loaded into a nested list by means of sheet <import list>.

 

Note that an assignment like #m1 = #m2;, where #m2 is a list, #m1 will become a copy of #m2, not a reference to it. The same is the case regarding function arguments, where manipulating #m1 inside the function body of f(#m1) will not affect #m1 after the function has been left.

 

The lists #all (all model variables), #endo (all endogenous variables), and #exo (all exogenous variables) and some more are defined beforehand, if a model is loaded by the MODEL statement. These lists are located in the Global databank. See list ?;.

 

The reader may wonder why it is not possible to add a list #m and a scalar %s like this: #+ %s, appending %s to #m? This is tempting, but then what about %s1 + %s2 + #+ %s3? Should this mean a list with %s1, then %s2, then the elements of #m, and lastly %s3? But if %s1 and %s2 are two strings, these strings are added into another string. And if they are values, the values are added first. Hence, to avoid such confusion, using + between a list and a scalar is disallowed (which is also the case in Python and other languages).

 

Regarding variable types and the Gekko type system, see the VAR section. In this appendix, variable assignment rules, including variable types, is explained in more detail.

 

Beware that any rep * in a list definition will be ignored (rep * is designed for timeseries calculations).

 

A Gekko list relates to the following in different languages:

 

Gekko: #= ('x', 2.2);.

R: list (holds different types of variables), <- list("x", 2.2). A R vector is similar, but holds only variables of the same type, for instance <- c("a","b","c"). Note that #m[%i] in Gekko returns the object at position %i, not a 1-element list containing the object, like R. Use #m[%i..%i] to get such a R-like slice. In this sense, #m[%i] in Gekko corresponds to m[[i]] in R.

Python: list (holds different types of variables), = ["x", 2.2]. Python has a built-in set type, with union(), intersection() and difference() methods. Note that for union(), Python uses operator | where Gekko uses ||, for intersection() Python uses operator & where Gekko uses &&, and for difference() both Python and Gekko use operator - (difference() is called except() in Gekko). Python sets do not allow dublets, but Python lists do not provide methods union(), intersection() and difference().

Matlab: same type elements: array, else: cell array, = {"x", 2.2}.

 

 


 

Related statements

 

MAP, MATRIX, FOR