CPSC 215

February (4^th), 2002

C. Jacob / S. Kaufmann

Calculating with Lists

Automatic Operations

Introductory Examples

Many functions of one argument are automatically mapped onto the elements of lists.

Sin[{1, 2, 3}]

This multiplies each element of the list by 3:

3 {a, b, c}

The (normal) product is calculated element-wise.

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

The Inner function

For more involved problems there are also the functions Inner and Outer, which calculate generalized inner and outer products.

Inner[f, {a, b}, {x, y}, g]

% /. {f -> Times, g -> Plus}

Inner[Times, {a, b}, {x, y}, Plus]

Inner[Plus, {a, b}, {x, y}, Times]

Inner[Range, {1, 100}, {5, 105}, Join]

Inner and the Scalar Vector Product

Closely related to the Inner command is the scalar product for vectors, using the Dot operation:

Dot[{x, y, z}, {u, v, w}]

A shorter notation for the scalar product is this:

{x, y, z} . {u, v, w}

Obviously, the Dot command is a shorter version for Inner with Times and Plus:

Inner[Times, {x, y, z}, {u, v, w}, Plus]

The Cross Product for Vectors

The cross product, Cross, for vectors is a little more complicated in its mathematical definition:

(({{x}, {y}, {z}}))×(({{u}, {v}, {w}}))=(({{y w - z v}, {-(x w  -  z u)}, {x v - y u}}))

Here is the same definition in Mathematica:

Cross[{x, y, z}, {u, v, w}]

We can even write this in the following notation:

{x, y, z}\[Cross]{u, v, w}

Writing our own Cross Product function

Here is how we can write our own cross product function using Inner:

myCross[{x_, y_, z_}, {u_, v_, w_}] := 
{Inner[
          Times, {y, z}, {w, -v}, Plus], 
Inner[
          Times, {-w, u}, {x, z}, Plus], 
Inner[
          Times, {v, u}, {x, -y}, Plus]}

myCross[{x, y, z}, {u, v, w}]

The Outer function

The Outer function gives the generalized outer product of lists:

Outer[f, {a, b}, {x, y}]

Essentially, the Outer function generates all combinations of arguments in the lists provided:

Outer[List, {True, False}, {True, False}] // TableForm

Outer[List, {0, 1}, {0, 1}, {0, 1}] // TableForm

\(Outer[
      StringJoin, {"a", "b", "c", "d"}, {"a", "b", "c", "d"}]\)

\(Outer[
      StringJoin, {"a", "b", "c", "d"}, {"a", "b", "c", "d"}, {"a", "b", "c", "d"}, {"a", "b", "c", "d"}]\)

Outer[StringJoin, 
      Sequence @@ Table[{"a", "b", "c"}, {3}]]

allWords[alphabet_List, wordLength_Integer] := 
      Outer[StringJoin, Sequence @@ Table[alphabet, {wordLength}]]

allWords[{"a", "b", "c", "d", "e"}, 5]

Flatten[%] // Length

Mapping Functions on Lists

The automatic mapping of functions on lists will not solve all our problems. For example, let us look at Variables which delivers the variables in a polynomial.

Variables[x + y]

If we apply this function to a list, we get a flat list of all variables in the original list.

Variables[{x + y, x + z, y}]

But what are the variables of the single elements of the list? An iteration over the elements is somewhat awkward:

Table[
      Variables[{x + y, x + z, y}[[i
          ]]], {i, 3}]

As part of a complicated program, this would have the disadvantage that we first have to determine the length (possible with Length) and that the construction is hard to read. Therefore Mathematica offers the possibility of mapping functions of one argument onto lists using Map.

Map[Variables, {x + y, x + z, y}]

Because Map appears often in programs, there is also a short notation:

Variables/@{x + y, x + z, y}

Pure Functions

In the example for Select we defined an auxiliary function

myTest[x_] = (x > 10) && (x < 50);

to recognize the desired list elements. Often we need this kind of tool only once, so there is no point in giving it a name. This can be avoided with the help of pure functions. The pure function for this problem can be written with Function and looks like this:

Function[x, (x > 10) && (x < 50)]

The first argument of Function contains the name of the auxiliary (local) variable x, the second argument is the expression in x to be evaluated. Such objects are applied in the usual way. In the following example the argument 9 is substituted for x and the function body evaluated.

Function[x, (x > 10) && (x < 50)][9]

Pure functions can easily be mapped on lists

Function[x, (x > 10) && (x < 50)] /@ {1, 20, 100, 30}

or used in functions like Select.

Select[Table[i^2, {i, 10}], Function[x, (x > 10) && (x < 50)]]

Now we do not need the name x in the pure function either. We can replace it with # and write only the function definition.

Select[Table[i^2, {i, 10}], Function[(# > 10) && (# < 50)]]

Because this also appears often, there is an even shorter way to write it: leave out the Function and delimitate the pure function with a &.

Select[Table[i^2, {i, 10}], (# > 10) && (# < 50)&]

In this way we can easily calculate the partial derivatives of the expression

((x - y)/(Sqrt[(x^2) + (y^2) + (z^2)]));

with respect to x, y, z, i.e. the gradient.

D[((x - y)/(Sqrt[(x^2) + (y^2) + (z^2)])), #]& /@ {x, y, z}

In a pure function with several arguments, these are either combined into a list (when Function is used with two arguments) or indicated with #1, #2, … (in the short notation).

Function[{x, y, z}, Sqrt[x^2 + y^2 + z^2]]

%[a, b, c]

Function[Sqrt[#1^2 + #2^2 + #3^2]][a, b, c]

Of course we can also write definitions with pure functions.

geometricMean = (#1 #2 #3)^(1/3)&;

geometricMean[a, b, c]

The alternative definition of the form

geometricMean1[x_, y_, z_] := (x y z)^(1/3)

geometricMean1[a, b, c]

is a definition for the pattern geometricMean1[x_,y_,z_]. In contrast, the pure function

geometricMean = (#1 #2 #3)^(1/3)&;

can be interpreted as a definition for the head geometricMean (see Section 4.1).

Using List Elements as Arguments

To conclude this first look at some exotic constructions, let us discuss Apply. It is used to apply the elements of a list as arguments of a function.

Apply[f, {a, b, c}]

This is, of course, different from:

f[{a, b, c}]

We now consider the addition function Plus which we normally write using the operator + (see Section 4.1). If we apply it to a list using Apply, we get the sum of the elements

Apply[Plus, {a, b, c}]

or, analogously, the product using Times:

Apply[Times, {a, b, c}]

There is also an infix notation:

Plus @@ {a, b, c}

Times @@ {a, b, c}

The above function for the geometric mean has the disadvantage that the number of arguments is set at three. We can now define a variation which handles a list of indeterminate length.

geometricMean2 = (Times@@#)^(1/Length[#])&;

geometricMean2[{a, b, c, d, e}]

Of course, we also have built-in functions for indexed sums and products: Sum and Product. They work like Table.

Sum[a^i, {i, 5}]

Plotting Lists

There are variations to almost all graphic functions to plot lists of values. Their names always begin with List (ListPlot, ListPlot3D, ListContourPlot, etc.). The data can be taken from Mathematica itself or can be imported from other programs using ReadList (see the in-depth section).

We create a list with a couple of numerical values of the cosine function.

cosList = Table[N[Cos[x]], {x, 0, 2  Pi, 2  Pi/50}];

ListPlot plots these points.

ListPlot[cosList];

They are joined with the option PlotJoined->True.

ListPlot[cosList, PlotJoined -> True];

The abscissa is labeled with the entry numbers in the list (1, … , 51) in this case. But we can also plot a list of point pairs, which gives us useful scales on both axes.

Short[xCosxList = Table[N[{x, Cos[x]}], {x, 0, 2  Pi, 2  Pi/50}]]

ListPlot[xCosxList];