Ch 2: Lists and Tables

| # Chapter 2: Lists and Tables Computations need data. So far we have seen data only as single numbers or lists of numbers. We can have other things by way of data, such as tables for example. Things like lists and tables are called "arrays". ## 2.1 Tables A table with, say, 2 rows and 3 columns can be built with the `$` function:
       table =: 2 3   $   5 6 7  8 9 10
       table
    5 6  7
    8 9 10
The scheme here is that the expression `(x $ y)` builds a table. The dimensions of the table are given by the list `x` which is of the form number-of-rows followed by number-of-columns. The elements of the table are supplied by the list `y`. Items from `y` are taken in order, so as to fill the first row, then the second, and so on. The list `y` must contain at least one item. If there are too few items in `y` to fill the whole table, then `y` is re-used from the beginning.
`2 4 $ 5 6 7 8 9` | `2 2 $ 1`
    5 6 7 8
    9 5 6 7
    1 1
    1 1
The `$` function offers one way to build tables, but there are many more ways: see Chapter 05. Functions can be applied to whole tables exactly as we saw earlier for lists:
`table` | `10 * table` | `table + table`
    5 6  7
    8 9 10
    50 60  70
    80 90 100
    10 12 14
    16 18 20
One argument can be a table and one a list:
`table` | `0 1 * table`
    5 6  7
    8 9 10
    0 0  0
    8 9 10
In this last example, evidently the items of the list `0 1` are automatically matched against the rows of the table, `0` matching the first row and `1` the second. Other patterns of matching the arguments against each other are also possible - see Chapter 07. ## 2.2 Arrays A table is said to have two dimensions (namely, rows and columns) and in this sense a list can be said to have only one dimension. We can have table-like data objects with more than two dimensions. The left argument of the `$` function can be a list of any number of dimensions. The word "array" is used as the general name for a data object with some number of dimensions. Here are some arrays with one, two and three dimensions:
`3 $ 1` | `2 3 $ 5 6 7` | `2 2 3 $ 5 6 7 8`
    1 1 1
    5 6 7
    5 6 7
    5 6 7
    8 5 6

    7 8 5
    6 7 8
The 3-dimensional array in the last example is said to have 2 planes, 2 rows and 3 columns and the two planes are displayed one below the other. Recall that the monadic function `#` gives the length of a list.
`# 6 7` | `# 6 7 8`
    2
    3
The monadic function `$` gives the list-of-dimensions of its argument:
`L =: 5 6 7` | `$ L` | `T =: 2 3 $ 1` | `$ T`
    5 6 7
    3
    1 1 1
    1 1 1
    2 3
Hence, if `x` is an array, the expression `(# $ x)` yields the length of the list-of-dimensions of `x`, that is, the dimension-count of `x`, which is `1` for a list, `2` for a table and so on.
`L` | `$ L` | `# $ L` | `T` | `$T` | `# $ T`
    5 6 7
    3
    1
    1 1 1
    1 1 1
    2 3
    2
If we take `x` to be a single number, then the expression `(# $ x)` gives zero.
       # $ 17
    0
We interpret this to mean that, while a table has two dimensions, and a list has one, a single number has none, because its dimension-count is zero. A data object with a dimension-count of zero will be called a scalar. We said that "arrays" are data objects with some number of dimensions, and so scalars are also arrays, the number of dimensions being zero in this case. We saw that `(# $ 17)` is `0`. We can also conclude from this that, since a scalar has no dimensions, its list-of-dimensions (given here by `$ 17`) must be a zero-length, or empty, list. Now a list of length 2, say can be generated by an expression such as `2 $ 99` and so an empty list, of length zero, can be generated by `0 $ 99` (or indeed, `0 $` any number) The value of an empty list is displayed as nothing:
`2 $ 99` | `0 $ 99` | `$ 17`
    99 99
Notice that a scalar, (`17` say), is not the same thing as a list of length one (e.g. `1 $ 17`), or a table with one row and one column (e.g. `1 1 $ 17`). The scalar has no dimensions, the list has one, the table has two, but all three look the same when displayed on the screen:
       S =: 17
       L =: 1 $ 17
       T =: 1 1 $ 17
`S` | `L` | `T` | `# $ S` | `# $ L` | `# $ T`
    17
    17
    17
    0
    1
    2
A table may have only one column, and yet still be a 2-dimensional table. Here `t` has 3 rows and 1 column.
`t =: 3 1 $ 5 6 7` | `$ t` | `# $ t`
    5
    6
    7
    3 1
    2
## 2.3 Terminology: Rank and Shape The property we called "dimension-count" is in J called by the shorter name of of "rank", so a single number is a said to be a rank-0 array, a list of numbers a rank-1 array and so on. The list-of-dimensions of an array is called its "shape". The mathematical terms "vector" and "matrix" correspond to what we have called "lists" and "tables" (of numbers). An array with 3 or more dimensions (or, as we now say, an array of rank 3 or higher) will be called a "report". A summary of terms and functions for describing arrays is shown in the following table.
    +--------+--------+-----------+------+
    |        | Example| Shape     | Rank |
    +--------+--------+-----------+------+
    |        | x      | $ x       | # $ x|
    +--------+--------+-----------+------+
    | Scalar | 6      | empty list| 0    |
    +--------+--------+-----------+------+
    | List   | 4 5 6  | 3         | 1    |
    +--------+--------+-----------+------+
    | Table  |0 1 2   | 2 3       | 2    |
    |        |3 4 5   |           |      |
    +--------+--------+-----------+------+
    | Report |0  1  2 | 2 2 3     | 3    |
    |        |3  4  5 |           |      |
    |        |        |           |      |
    |        |6  7  8 |           |      |
    |        |9 10 11 |           |      |
    +--------+--------+-----------+------+
This table above was in fact produced by a small J program, and is a genuine "table", of the kind we have just been discussing. Its shape is `6 4`. However, it is evidently not just a table of numbers, since it contains words, list of numbers and so on. We now look at arrays of things other than numbers. ## 2.4 Arrays of Characters Characters are letters of the alphabet, punctuation, numeric digits and so on. We can have arrays of characters just as we have arrays of numbers. A list of characters is entered between single quotes, but is displayed without the quotes. For example:
       title =: 'My Ten Years in a Quandary'
       title
    My Ten Years in a Quandary
A list of characters is called a character-string, or just a string. A single quote in a string is entered as two successive single quotes.
       'What''s new?'
    What's new?
An empty, or zero-length, string is entered as two successive single quotes, and displays as nothing.
`''` | `# ''`
    0
## 2.5 Some Functions for Arrays At this point it will be useful to look at some functions for dealing with arrays. J is very rich in such functions: here we look at a just a few. ### 2.5.1 Joining The built-in function `,` (comma) is called "Append". It joins things together to make lists.
`a =: 'rear'` | `b =: 'ranged'` | `a,b`
    rear
    ranged
    rearranged
The "Append" function joins lists or single items.
`x =: 1 2 3` | `0 , x` | `x , 0` | `0 , 0` | `x , x`
    1 2 3
    0 1 2 3
    1 2 3 0
    0 0
    1 2 3 1 2 3
The "Append" function can take two tables and join them together end-to-end to form a longer table:
`T1=: 2 3 $ 'catdog'` | `T2=: 2 3 $ 'ratpig'` | `T1,T2`
    cat
    dog
    rat
    pig
    cat
    dog
    rat
    pig
For more information about "Append", see Chapter 05. ### 2.5.2 Items The items of a list of numbers are the individual numbers, and we will say that the items of a table are its rows. The items of a 3-dimensional array are its planes. In general we will say that the items of an array are the things which appear in sequence along its first dimension. An array is the list of its items. Recall the built-in verb `#` ("Tally") which gives the length of a list.
`x` | `# x`
    1 2 3
    3
In general `#` counts the number of items of an array, that is, it gives the first dimension:
`T1` | `$ T1` | `# T1`
    cat
    dog
    2 3
    2
Evidently `# T1` is the first item of the list-of-dimensions `$ T1`. A scalar, with no dimensions, is regarded as a single item:
       # 6
    1
Consider again the example of "Append" given above.
`T1` | `T2` | `T1 , T2`
    cat
    dog
    rat
    pig
    cat
    dog
    rat
    pig
Now we can say that in general `(x , y)` is a list consisting of the items of `x` followed by the items of `y`. For another example of the usefulness of "items", recall the verb `+/` where `+` is inserted between items of a list.
`+/ 1 2 3` | `1 + 2 + 3`
    6
    6
Now we can say that in general `+/` inserts `+` between items of an array. In the next example the items are the rows:
`T =: 3 2 $ 1 2 3 4 5 6` | `+/ T` | `1 2 + 3 4 + 5 6`
    1 2
    3 4
    5 6
    9 12
    9 12
### 2.5.3 Selecting Now we look at selecting items from a list. Positions in a list are numbered `0, 1, 2` and so on. The first item occupies position `0`. To select an item by its position we use the function `{` (left brace, called "From") .
`y =: 'abcd'` | `0 { y` | `1 { y` | `3{ y`
    abcd
    a
    b
    d
A position-number is called an index. The `{` function can take as left argument a single index or a list of indices:
`y` | `0 { y` | `0 1 { y` | `3 0 1 { y`
    abcd
    a
    ab
    dab
There is a built-in function `i.` (letter-i dot). The expression `(i. n)` generates `n` successive integers from zero.
`i. 4` | `i. 6` | `1 + i. 3`
    0 1 2 3
    0 1 2 3 4 5
    1 2 3
If `x` is a list, the expression `(i. # x)` generates all the possible indexes into the list `x`.
`x =: 'park'` | `# x` | `i. # x`
    park
    4
    0 1 2 3
With a list argument, `i.` generates an array:
       i. 2 3
    0 1 2
    3 4 5
There is a dyadic version of `i.`, called "Index Of". The expression `(x i. y)` finds the position, that is, index, of `y` in `x`.
       'park' i. 'k'
    3
The index found is that of the first occurrence of `y` in `x`.
       'parka' i. 'a'
    1
If `y` is not present in `x`, the index found is 1 greater than the last possible position.
       'park' i. 'j'
    4
For more about the many variations of indexing, see Chapter 06. ### 2.5.4 Equality and Matching Suppose we wish to determine whether two arrays are the same. There is a built-in verb `-:` (minus colon, called "Match"). It tests whether its two arguments have the same shapes and the same values for corresponding elements.
`x =: 'abc'` | `x -: x` | `y =: 1 2 3 4` | `x -: y`
    abc
    1
    1 2 3 4
    0
Whatever the arguments, the result of Match is always a single `0` or `1`. Notice that an empty list of, say, characters is regarded as matching an empty list of numbers:
       '' -: 0 $ 0
    1
because they have the same shapes, and furthermore it is true that all corresponding elements have the same values, (because there are no such elements). There is another verb, `=` (called "Equal") which tests its arguments for equality. `=` compares its arguments element by element and produces an array of booleans of the same shape as the arguments.
`y` | `y = y` | `y = 2`
    1 2 3 4
    1 1 1 1
    0 1 0 0
Consequently, the two arguments of `=` must have the same shapes, (or at least, as in the example of `y=2`, compatible shapes). Otherwise an error results.
`y` | `y = 1 5 6 4` | `y = 1 5 6`
    1 2 3 4
    1 0 0 1
    error
## 2.6 Arrays of Boxes ### 2.6.1 Linking There is a built-in function `;` (semicolon, called "Link"). It links together its two arguments to form a list. The two arguments can be of different kinds. For example we can link together a character-string and a number.
       A =: 'The answer is'  ;  42
       A
    +-------------+--+
    |The answer is|42|
    +-------------+--+
The result `A` is a list of length 2, and is said to be a list of boxes. Inside the first box of `A` is the string `'The answer is'`. Inside the second box is the number `42`. A box is shown on the screen by a rectangle drawn round the value contained in the box.
`A` | `0 { A`
    +-------------+--+
    |The answer is|42|
    +-------------+--+
    +-------------+
    |The answer is|
    +-------------+
A box is a scalar whatever kind of value is inside it. Hence boxes can be packed into regular arrays, just like numbers. Thus `A` is a list of scalars.
`A` | `$ A` | `s =: 1 { A` | `# $ s`
    +-------------+--+
    |The answer is|42|
    +-------------+--+
    2
    +--+
    |42|
    +--+
    0
The main purpose of an array of boxes is to assemble into a single variable several values of possibly different kinds. For example, a variable which records details of a purchase (date, amount, description) could be built as a list of boxes:
       P =: 18 12 1998  ;  1.99  ;  'baked beans'
       P
    +----------+----+-----------+
    |18 12 1998|1.99|baked beans|
    +----------+----+-----------+
Note the difference between "Link" and "Append". While "Link" joins values of possibly different kinds, "Append" always joins values of the same kind. That is, the two arguments to "Append" must both be arrays of numbers, or both arrays of characters, or both arrays of boxes. Otherwise an error is signalled.
`'answer is'; 42` | `'answer is' , 42`
    +---------+--+
    |answer is|42|
    +---------+--+
    error
On occasion we may wish to combine a character-string with a number, for example to present the result of a computation together with some description. We could "Link" the description and the number, as we saw above. However a smoother presentation could be produced by converting the number to a string, and then Appending this string and the description, as characters. Converting a number to a string can be done with the built-in "Format" function `":` (double-quote colon). In the following example `n` is a single number, while `s`, the formatted value of `n`, is a string of characters of length 2.
`n =: 42` | `s =: ": n` | `# s` | `'answer is ' , s`
    42
    42
    2
    answer is 42
For more about "Format", see Chapter 19. Now we return to the subject of boxes. Because boxes are shown with rectangles drawn round them, they lend themselves to presentation of results on-screen in a simple table-like form.
       p =: 4 1 $ 1 2 3 4
       q =: 4 1 $ 3 0 1 1

       2 3 $ ' p ' ; ' q ' ; ' p+q ' ;  p ; q ; p+q
    +---+---+-----+
    | p | q | p+q |
    +---+---+-----+
    |1  |3  |4    |
    |2  |0  |2    |
    |3  |1  |4    |
    |4  |1  |5    |
    +---+---+-----+
### 2.6.2 Boxing and Unboxing There is a built-in function `<` (left-angle-bracket, called "Box"). A single boxed value can be created by applying `<` to the value.
       < 'baked beans'
    +-----------+
    |baked beans|
    +-----------+
Although a box may contain a number, it is not itself a number. To perform computations on a value in a box, the box must be, so to speak "opened" and the value taken out. The function (`>` (right-angle-bracket) is called "Open".
`b =: < 1 2 3` | `> b`
    +-----+
    |1 2 3|
    +-----+
    1 2 3
It may be helpful to picture `<` as a funnel. Flowing into the wide end we have data, and flowing out of the narrow end we have boxes which are scalars, that is, dimensionless or point-like. Conversely for `>` . Since boxes are scalars, they can be strung together into lists of boxes with the comma function, but the semicolon function is often more convenient because it combines the stringing-together and the boxing:
`(< 1 1) , (< 2 2) , (< 3 3)` | `1 1 ; 2 2 ; 3 3`
    +---+---+---+
    |1 1|2 2|3 3|
    +---+---+---+
    +---+---+---+
    |1 1|2 2|3 3|
    +---+---+---+
## 2.7 Summary In conclusion, every data object in J is an array, with zero, one or more dimensions. An array may be an array of numbers, or an array of characters, or an array of boxes (and there are further possibilities). This brings us to the end of Chapter 2.

NEXT
Table of Contents
Index

Copyright © Roger Stokes 2005. This material may be freely reproduced, provided that this copyright notice is also reproduced.

last updated 25 Jan 2005