next | previous | forward | backward | up | top | index | toc | Macaulay2 web site
Macaulay2Doc > The Macaulay2 language > lists and sequences

lists and sequences -- a detailed overview of lists and sequences in Macaulay2

This page gives an overview of the use of lists of all types, including:

basic lists (of class BasicList),
visible lists (of class VisibleList),
lists (of class List),
sequences (of class Sequence),
arrays (of class Array), and
mutable lists (of class MutableList).

The sections of the overview are, in order:

Creating lists; kinds of lists.
Elements and indexing.
Nested lists.
Ranges and repetitions.
Manipulating lists and sequences.
Mapping over lists.
Conditional expressions; selecting elements matching a criterion.

Links to individual documentation pages for the functions described in this article are collected in an alphabetized list at the very end of the page.

Creating lists; kinds of lists.

To create a list, use curly braces around a comma-separated series of elements.

i1 : L = {a,b,c,d,e}

o1 = {a, b, c, d, e}

o1 : List

Sequences are created and displayed using parentheses instead of braces.

i2 : S = (a,b,c,d,e)

o2 = (a, b, c, d, e)

o2 : Sequence

Sequences are implemented in a more efficient way than lists, since a sequence is created every time a function is called with more than one argument. On the other hand, parentheses are also used for grouping algebraic expressions. This complicates some tasks, such as creating a sequence of length 1.

i3 : ()

o3 = ()

o3 : Sequence
i4 : (1,2)

o4 = (1, 2)

o4 : Sequence
i5 : (1)

o5 = 1

The functions toList and toSequence, which convert between lists and sequences, may be useful here.

i6 : toSequence {1}

o6 = 1 : (1)

o6 : Sequence

Lists and sequences can be used as vectors, provided their elements are the sorts of things that can be added and mutliplied.

i7 : 10000*{3,4,5} + {1,2,3}

o7 = {30001, 40002, 50003}

o7 : List

An array is another type of list, created and displayed using square brackets. Unlike lists and sequences, arrays can’t be used as vectors. Their main use is notational; for example, they appear in the construction of polynomial rings.

i8 : v = [1,2,3]

o8 = [1, 2, 3]

o8 : Array
i9 : ZZ[a,b,c]

o9 = ZZ[a, b, c]

o9 : PolynomialRing

Lists, sequences, and arrays are the three examples of what we call visible lists, which constitute the class VisibleList. Many functions are defined to act uniformly on visible lists. There is a type of list more general than a visible list, which we call a BasicList. Basic lists are a secure choice for defining new datatypes, since the many functions that act on visible lists do not act on basic lists. Here we illustrate how to create a new type of basic list, in this case called Container.

i10 : Container = new Type of BasicList

o10 = Container

o10 : Type
i11 : t = new Container from {a,b}

o11 = Container{a, b}

o11 : Container

We can then declare a new method for the operator ++ that will join two Containers:

i12 : Container ++ Container := join;
i13 : t ++ t

o13 = Container{a, b, a, b}

o13 : Container

Basic lists are normally immutable; that is, no element can be replaced, added, or removed. (Functions like append, and the many others described in the Manipulating lists and sequences section, will return a new list in Macaulay2, as a general rule, rather than modify the existing list.)

However, there is a certain type of basic list, called a mutable list (of class MutableList), whose elements can be changed. This allows the possibility of creating circular structures that would cause a print routine to go into an infinite loop. To avoid such infinite loops, the contents of mutable lists are not printed. Instead, use peek to display the elements in a controlled way.

i14 : A = new MutableList from {a,b,c}

o14 = MutableList{...3...}

o14 : MutableList
i15 : peek A

o15 = MutableList{a, b, c}
i16 : A#2 = 1234;
i17 : A

o17 = MutableList{...3...}

o17 : MutableList
i18 : peek A

o18 = MutableList{a, b, 1234}

Because the contents of mutable lists are not printed, they can be used as containers for big things one doesn’t want to print. Although any mutable list can be used in this way, there is a a special type of mutable list called a Bag, which is designed for this purpose. When printed, the bag displays only a little information about its contents.

i19 : r = Bag {100!}; r

o20 = -*a bagged integer*-

o20 : Bag
i21 : q = Bag {1/100!}; q

o22 = -*a bagged rational number*-

o22 : Bag
i23 : unbag q

                                                                             
o23 = -----------------------------------------------------------------------
      93326215443944152681699238856266700490715968264381621468592963895217599
      =======================================================================
              1
      -----------------------------------------------------------------------
      99322991560894146397615651828625369792082722375825118521091686400000000
      =======================================================================
      ----------------
      0000000000000000

o23 : QQ

The hierarchy of types mentioned above is summarized here using showStructure:

i24 : showStructure(List,Sequence,Array,Container,MutableList,Bag,BasicList)

o24 = Thing : BasicList : Container
                          MutableList : Bag
                          VisibleList : Array
                                        List
                                        Sequence

o24 : Descent

Elements and indexing.

We retrieve the length of a list with the operator # or with the function length.

i25 : L = {926, 621, 429, 67, 594, 904, 264, 18, 35, 961};
i26 : #L

o26 = 10
i27 : length L

o27 = 10

The expression L#n returns the nth element of L. The elements are numbered consecutively starting with 0. Alternatively, they are numbered consecutively ending with -1.

i28 : L#0

o28 = 926
i29 : L#2

o29 = 429
i30 : L#-1

o30 = 961

The _ operator is similar to #, except that it can also take a list or range of indices. However, it may only be used with visible lists.

i31 : L_1

o31 = 621
i32 : L_{3,6}

o32 = {67, 264}

o32 : List

The functions first and last retrieve the first and last elements of a list.

i33 : first L

o33 = 926
i34 : last L

o34 = 961

Omitting an element of a list causes the symbol null to be inserted in its place. When the value of an expression is null, like when we ask for A#2 in the next example, the output line doesn’t appear at all.

i35 : A = {3,4,,5}

o35 = {3, 4, , 5}

o35 : List
i36 : peek A

o36 = {3, 4, null, 5}
i37 : A#2

Ranges and repetitions.

The operator .. can be used to create sequences of numbers, sequences of subscripted variables, and so on.

i38 : 1 .. 5, x_1 .. x_5, a .. e

o38 = ((1, 2, 3, 4, 5), (x , x , x , x , x ), (a, b, c, d, e))
                          1   2   3   4   5

o38 : Sequence

The operator ZZ : Thing creates a sequence by replicating an element a given number of times.

i39 : 12:a

o39 = (a, a, a, a, a, a, a, a, a, a, a, a)

o39 : Sequence

Replicating something once is another way to create a sequence of length 1, which cannot be entered by simply typing parentheses.

i40 : 1:a

o40 = 1 : (a)

o40 : Sequence

Both .. and : produce sequences, and may not behave as expected with respect to nesting. For instance, to create the list {3, 4, 5, 6, 9, 12, 12, 12}, the following command will not work:

i41 : A = {3 .. 6, 9, 3:12}

o41 = {(3, 4, 5, 6), 9, (12, 12, 12)}

o41 : List

Instead, we get a list of length 3, some of whose elements are sequences. This is easily resolved with splice.

i42 : A = splice {3..6, 9, 3:12}

o42 = {3, 4, 5, 6, 9, 12, 12, 12}

o42 : List

However, many operators and functions will automatically splice lists for you. Two examples are the array of variables defining a polynomial ring, and the indices passed to the _ operator.

i43 : QQ[a..c,x_1..x_4]

o43 = QQ[a, b, c, x , x , x , x ]
                   1   2   3   4

o43 : PolynomialRing
i44 : L_{1..3,-3..-1}

o44 = {621, 429, 67, 18, 35, 961}

o44 : List

Nested lists.

When the elements of a list are themselves lists, we call it a nested list.

i45 : A = {{a,b,c},{d,{e,f}}}

o45 = {{a, b, c}, {d, {e, f}}}

o45 : List
i46 : #A

o46 = 2
i47 : #(first A)

o47 = 3

One level of nesting may be eliminated with flatten.

i48 : flatten A

o48 = {a, b, c, d, {e, f}}

o48 : List

The function splice acts analogously on sequences, removing those pairs of parentheses that are one level inward.

i49 : splice (a, (b, c), (d, (e, f, (g, h))) )

o49 = (a, b, c, d, (e, f, (g, h)))

o49 : Sequence

To remove all layers of nesting at once, use deepSplice.

i50 : deepSplice (a, (b, c), (d, (e, f, (g, h))) )

o50 = (a, b, c, d, e, f, g, h)

o50 : Sequence

A table is a list whose elements are lists all of the same length. The inner lists are regarded as rows when the table is displayed as a two-dimensional array with MatrixExpression.

i51 : T = {{a,1},{b,2},{c,3}}

o51 = {{a, 1}, {b, 2}, {c, 3}}

o51 : List
i52 : isTable T

o52 = true
i53 : MatrixExpression T

o53 = | a  1 |
      |      |
      | b  2 |
      |      |
      | c  3 |

o53 : Expression of class MatrixExpression

The function table can be used to create a table (doubly nested list) from two lists and a function of two arguments. It applies the function consecutively to each element from the first list paired with each element from the second list, so the total number of evaluations of the function is the product of the lengths of the two lists.

i54 : table({1,2,3},{7,8},(i,j) -> 1000*i+j)

o54 = {{1007, 1008}, {2007, 2008}, {3007, 3008}}

o54 : List

The function pack(L, n) turns the list L into a nested list, whose elements are lists containing the elements of L taken n at a time.

i55 : pack(1..15, 4)

o55 = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15}}

o55 : List

On the other hand, mingle(L) takes the nested list L = {L1, L2, ..., Ln} and combines the elements of the Li into a single list in the following way:

i56 : mingle({{1,2,3,4}, {10,20,30,40}, {100,200,300,400}, {a, b}})

o56 = {1, 10, 100, a, 2, 20, 200, b, 3, 30, 300, 4, 40, 400}

o56 : List

Manipulating lists and sequences.

Use append(L, x) to create a copy of L with the element x added to the end. Since lists are immutable in Macaulay2, L itself is not changed, unless redefined.

i57 : 
      
      L = {926, 621, 429, 67, 594, 904, 264, 18, 35, 961};
i58 : append(L, -10)

o58 = {926, 621, 429, 67, 594, 904, 264, 18, 35, 961, -10}

o58 : List
i59 : L

o59 = {926, 621, 429, 67, 594, 904, 264, 18, 35, 961}

o59 : List
i60 : L = append(L, -10); L

o61 = {926, 621, 429, 67, 594, 904, 264, 18, 35, 961, -10}

o61 : List

Use prepend(x, L) to create a copy of L with x added to the beginning of the list. Notice the order of arguments is the opposite of append!

i62 : L = prepend(-20, L)

o62 = {-20, 926, 621, 429, 67, 594, 904, 264, 18, 35, 961, -10}

o62 : List

Use insert(n, x, L) to specify that the element x should be added to the list L at position n.

i63 : L = insert(5, -30, L)

o63 = {-20, 926, 621, 429, 67, -30, 594, 904, 264, 18, 35, 961, -10}

o63 : List

Use switch(m, n, L) to switch the elements of L in indices m and n.

i64 : L = switch(1, 2, L)

o64 = {-20, 621, 926, 429, 67, -30, 594, 904, 264, 18, 35, 961, -10}

o64 : List

The function delete removes elements that have a particular value, NOT a particular index.

i65 : L = delete(-10, L)

o65 = {-20, 621, 926, 429, 67, -30, 594, 904, 264, 18, 35, 961}

o65 : List

To remove the element at index n, use the command drop(L, {n,n}).

i66 : L = drop(L, {1,1})

o66 = {-20, 926, 429, 67, -30, 594, 904, 264, 18, 35, 961}

o66 : List

You can also use drop to remove a specified number of elements from the beginning or end of L.

i67 : L = drop(L, 2)

o67 = {429, 67, -30, 594, 904, 264, 18, 35, 961}

o67 : List
i68 : L = drop(L, -2)

o68 = {429, 67, -30, 594, 904, 264, 18}

o68 : List

On the other hand, use take to specify the number of elements to keep, or a range of indices to keep:

i69 : L = take(L, 6)

o69 = {429, 67, -30, 594, 904, 264}

o69 : List
i70 : L = take(L, {1,4})

o70 = {67, -30, 594, 904}

o70 : List

Use between(x, L) to insert the element x between every two elements of L.

i71 : L = between(-5, L)

o71 = {67, -5, -30, -5, 594, -5, 904}

o71 : List

Useful commands for reordering lists are reverse (reverse the current order), sort (put elements in ascending order), and rsort (put elements in descending order).

i72 : L

o72 = {67, -5, -30, -5, 594, -5, 904}

o72 : List
i73 : reverse L

o73 = {904, -5, 594, -5, -30, -5, 67}

o73 : List
i74 : sort L

o74 = {-30, -5, -5, -5, 67, 594, 904}

o74 : List
i75 : rsort L

o75 = {904, 594, 67, -5, -5, -5, -30}

o75 : List

Use unique to remove duplicates from a list or sequence.

i76 : unique L

o76 = {67, -5, -30, 594, 904}

o76 : List

Use join to concatenate two lists or sequences. The symbol | is also used for concatenation.

i77 : join(a..f, 1..6)

o77 = (a, b, c, d, e, f, 1, 2, 3, 4, 5, 6)

o77 : Sequence
i78 : x_1..x_3 | y_1..y_4

o78 = (x , x , x , y , y , y , y )
        1   2   3   1   2   3   4

o78 : Sequence

Mapping over lists.

In programming, loops that operate on consecutive elements of a list are common, so we offer various ways to apply functions to each of the elements of a list, along with various ways to treat the returned values.

The most basic operation is provided by scan, which applies a function consecutively to each element of a list, discarding the values returned.

i79 : scan({a,b,c}, print)
a
b
c

The keyword break can be used to terminate the scan prematurely, and optionally to specify a return value for the expression. Here we use it to locate the first even number in a list.

i80 : scan({3,5,7,11,44,55,77}, i -> if even i then break i)

o80 = 44

The function apply is similar to scan, but creates a list storing the values returned.

i81 : apply({1,2,3,4}, i -> i^2)

o81 = {1, 4, 9, 16}

o81 : List

This operation is so common that we offer two shorthand notations for it, one with the function on the right and one with the function on the left.

i82 : {1,2,3,4} / (i -> i^2)

o82 = {1, 4, 9, 16}

o82 : List
i83 : (i -> i^2) \ {1,2,3,4}

o83 = {1, 4, 9, 16}

o83 : List

The associativity of these operators during parsing is set up so the following code works as one would wish.

i84 : {1,2,3,4} / (i -> i^2) / (j -> 1000*j)

o84 = {1000, 4000, 9000, 16000}

o84 : List
i85 : (j -> 1000*j) \ (i -> i^2) \ {1,2,3,4}

o85 = {1000, 4000, 9000, 16000}

o85 : List
i86 : (j -> 1000*j) @@ (i -> i^2) \ {1,2,3,4}

o86 = {1000, 4000, 9000, 16000}

o86 : List

The function apply can also be used with two lists of the same length, in which case it will apply the function consecutively to corresponding elements of the two lists.

i87 : apply({1,2,3}, {7,8,9}, (i,j) -> 1000*i+j)

o87 = {1007, 2008, 3009}

o87 : List

The function applyTable can be used to apply a function to each element of a table.

i88 : applyTable( {{1,2,3},{4,5}}, i -> i^2)

o88 = {{1, 4, 9}, {16, 25}}

o88 : List

The functions fold and accumulate provide various ways to iteratively apply a function of two arguments to the elements of a list. One of the arguments is the next element from the list, and the other argument is the value returned by the previous application of the function. As an example, suppose we want to convert the list {7,3,5,4,2} of digits into the corresponding number 73542. The formula (((7*10+3)*10+5)*10+4)+2 is a fast way to do it that doesn’t involve computing high powers of 10 separately. We can do this with fold and the following code.

i89 : fold((i,j) -> i*10+j, {7,3,5,4,2})

o89 = 73542

Using accumulate returns all the intermediate values of this iterative calculation along with the final result.

i90 : accumulate((i,j) -> i*10+j, {7,3,5,4,2})

o90 = {73, 735, 7354, 73542}

o90 : List

Conditional expressions; selecting elements matching a criterion.

Use select to select those elements from a list that satisfy some condition.

i91 : select({12, 3, -10, 42, 7, 6, 53}, even)

o91 = {12, -10, 42, 6}

o91 : List
i92 : select({12, 3, -10, 42, 7, 6, 53}, i -> i<0 or i>40)

o92 = {-10, 42, 53}

o92 : List

An optional first argument of an integer n specifies to select no more than n matching elements.

i93 : select(2, {12, 3, -10, 42, 7, 6, 53}, even)

o93 = {12, -10}

o93 : List

Use positions to select the indices of elements satisfying the condition.

i94 : positions({12, 3, -10, 42, 7, 6, 53}, i -> i<0 or i>40)

o94 = {2, 3, 6}

o94 : List

The singular position returns only the first (or last, by specifying Reverse => true) matching index.

i95 : position({12, 3, -10, 42, 7, 6, 53}, i -> i<0 or i>40)

o95 = 2
i96 : position({12, 3, -10, 42, 7, 6, 53}, i -> i<0 or i>40, Reverse => true)

o96 = 6

Use number to count how many elements satisfy the condition.

i97 : number({12, 3, -10, 42, 7, 6, 53}, i -> i<0 or i>40)

o97 = 3

Use max and min to find the maximum or minimum of the list. The functions maxPosition and minPosition give the index of the maximum/minimum. Note that max and min work with many Macaulay2 types besides numbers, for instance elements of a polynomial ring with respect to a monomial order.

i98 : R = QQ[x,y,z, MonomialOrder => Lex];
i99 : max {x^2*y*z, x*y^3*z^2, x^3, y^3, z}

       3
o99 = x

o99 : R
i100 : maxPosition {x^2*y*z, x*y^3*z^2, x^3, y^3, z}

o100 = 2
i101 : min {x^2*y*z, x*y^3*z^2, x^3, y^3, z}

o101 = z

o101 : R
i102 : minPosition {x^2*y*z, x*y^3*z^2, x^3, y^3, z}

o102 = 4

We may use any to tell whether there is at least one element of a list satisfying a condition, and all to tell whether all elements satisfy it.

i103 : any({3, 6, 7, 8}, even)

o103 = true
i104 : all({3, 6, 7, 8}, even)

o104 = false

See also