Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions

  




 

 

Multi-Dimensional Arrays or Matrices

There are situations that demand multi-dimensional arrays or matrices. In many languages (Java, COBOL, BASIC) this notion of multi-dimensionality is handled by pre-declaring the dimensions (and limiting the sizes of each dimension). In Python, these are handled somewhat more simply.

If you have a need for more sophisticated processing than we show in this section, you'll need to get the Python Numeric module, also known as NumPy. This is a Source Forge project, and can be found at http://numpy.sourceforge.net/.

Let's look at a simple two-dimensional tabular summary. When rolling two dice, there are 36 possible outcomes. We can tabulate these in a two-dimensional table with one die in the rows and one die in the columns:

1 2 3 4 5 6
1 2 3 4 5 6 7
2 3 4 5 6 7 8
3 4 5 6 7 8 9
4 5 6 7 8 9 10
5 6 7 8 9 10 11
6 7 8 9 10 11 12

In Python, a multi-dimensional table like this can be implemented as a sequence of sequences. A table is a sequence of rows. Each row is a sequence of individual cells. This allows us to use mathematical-like notation. Where the mathematician might say Ai,j , in Python we can say A[i][j]. In Python, we want the row i from table A, and column j from that row.

This looks remarkably like the list of tuples we discussed in the section called “Lists of Tuples”.

List of Lists Example. We can build a table using a nested list comprehension. The following example creates a table as a sequence of sequences and then fills in each cell of the table.

table= [ [ 0 for i in range(6) ] for j in range(6) ]
print table
for d1 in range(6):
    for d2 in range(6):
        table[d1][d2]= d1+d2+2
print table

This program produced the following output.

[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], 
[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]
[[2, 3, 4, 5, 6, 7], [3, 4, 5, 6, 7, 8], [4, 5, 6, 7, 8, 9], 
[5, 6, 7, 8, 9, 10], [6, 7, 8, 9, 10, 11], [7, 8, 9, 10, 11, 12]]

This program did two things. It created a six by six table of zeroes. It then filled this with each possible combination of two dice. This is not the most efficient way to do this, but we want to illustrate several techniques with a simple example. We'll look at each half in detail.

The first part of this program creates and prints a 6-item list, named table; each item in the table is a 6-item list of zeroes. It uses a list comprehension to create an object for each value of j in the range of 0 to 6. Each of the objects is a list of zeroes, one for each value of i in the range of 0 to 6. After this initialization, the two-dimensional table of zeroes is printed.

The comprehension can be read from inner to outer, like an ordinary expression. The inner list, [ 0 for i in range(6) ], creates a simple list of six zeroes. The outer list, [ [...] for j in range(6) ] creates six copies of these inner lists.

The second part of this program then iterates over all combinations of two dice, filling in each cell of the table. This is done as two nested loops, one loop for each of the two dice. The outer enumerates all values of one die, d1. The loop enumerates all values of a second die, d2.

Updating each cell involves selecting the row with table[d1]; this is a list of 6 values. The specific cell in this list is selected by ...[d2]. We set this cell to the number rolled on the dice, d1+d2+2.

Additional Examples. The printed list of lists is a little hard to read. The following loop would display the table in a more readable form.

>>> 
for row in table:

... 
    print row

... 
[2, 3, 4, 5, 6, 7]
[3, 4, 5, 6, 7, 8]
[4, 5, 6, 7, 8, 9]
[5, 6, 7, 8, 9, 10]
[6, 7, 8, 9, 10, 11]
[7, 8, 9, 10, 11, 12]
            

As an exercise, we'll leave it to the reader to add some features to this to print column and row headings along with the contents. As a hint, the "%2d" % value string operation might be useful to get fixed-size numeric conversions.

Explicit Index Values. We'll summarize our table of die rolls, and accumulate a frequency table. We'll use a simple list with 13 buckets (numbered from 0 to 12) for the frequency of each die roll. We can see that the die roll of 2 occurs just once in our matrix, so we'll expact that fq[2] will have the value 1. Let's visit each cell in the matrix and accumulate a frequency table.

There is an alternative to this approach. Rather than strip out each row sequence, we could use explicit indexes and look up each individual value with an integer index into the sequence.

fq= 13*[0]
for i in range(6):
    for j in range(6):
        c= table[i][j]
        fq[ c ] += 1

We initialize the frequency table, fq, to be a list of 13 zeroes.

The outer loop sets the variable i to the values from 0 to 5. The inner loop sets the variable j to the values from 0 to 5.

We use the index value of i to select a row from the table, and the index value of j to select a column from that row. This is the value, c. We then accumulate the frequency occurances in the frequency table, fq.

This looks very mathematical and formal. However, Python gives us an alternative, which can be somewhat simpler.

Using List Iterators Instead of Index Values. Since our table is a list of lists, we can make use of the power of the for statement to step through the elements without using an index.

fq= 13*[0]
print fq
for row in table:
    for c in row:
        fq[c] += 1
print fq[2:]

We initialize the frequency table, fq, to be a list of 13 zeroes.

The outer loop sets the variable row to each element of the original table variable. This decomposes the table into individual rows, each of which is a 6-element list.

The inner loop sets the variable c to each column's value within the row. This decomposes the row into the individual values.

We count the actual occurances of each value, c by using the value as an index into the frequency table, fq. The increment the frequency value by 1.

Mathematical Matrices. We use the explicit index technique for managing the mathematically-defined matrix operations. Matrix operations are done more clearly with this style of explicit index operations. We'll show matrix addition as an example, here, and leave matrix multplication as an exercise in a later section.

m1 = [ [1, 2, 3, 0], [4, 5, 6, 0], [7, 8, 9, 0] ]
m2 = [ [2, 4, 6, 0], [1, 3, 5, 0], [0, -1, -2, 0] ]
m3= [ 4*[0] for i in range(3) ]

for i in range(3):
    for j in range(4):
        m3[i][j]= m1[i][j]+m2[i][j]

In this example we created two input matrices, m1 and m2, each three by four. We initialized a third matrix, m3, to three rows of four zeroes, using a comprehension. Then we iterated through all rows (using the i variable), and all columns (using the j variable) and computed the sum of m1 and m2.

Python provides a number of modules for handling this kind of processing. In Part IV, “Components, Modules and Packages” we'll look at modules for more sophisticated matrix handling.


 
 
  Published under the terms of the Open Publication License Design by Interspire