views:

401

answers:

7

I know you can create easily nested lists in python like this:

[[1,2],[3,4]]

But how to create a 3x3x3 matrix of zeroes?

[[[0] * 3 for i in range(0, 3)] for j in range (0,3)]

or

[[[0]*3]*3]*3

Doesn't seem right. There is no way to create it just passing a list of dimensions to a method? Ex:

CreateArray([3,3,3])
A: 

Do you mean like this?

[[[0]*3]*3]*3
Matthew Mitchell
Yes, you answered the question, but I rewrote it to show what I really wanted.
Jader Dias
Don't do this - it almost certainly isn't what you want. This creates a list with 3 zeroes. It then creates a list with 3 *references* to that *same* list, and then another one with 3 references to *that*. If you never modify it, you won't care, but if you do, you'll end up modifying every row, because they all refer to the same list. (Eg. try l[0][0][0]=1 and then print l)
Brian
A: 

Just nest the multiplication syntax:

[[[0] * 3] * 3] * 3

It's therefore simple to express this operation using folds

def zeros(dimensions):
    return reduce(lambda x, d: [x] * d, [0] + dimensions)

Or if you want to avoid reference replication, so altering one item won't affect any other you should instead use copies:

import copy
def zeros(dimensions):
    item = 0
    for dimension in dimensions:
        item = map(copy.copy, [item] * dimension)
   return item
Dario
please allow my edit
Jader Dias
@Jader Dias: Amen
Dario
now using map!!
Jader Dias
+1  A: 

NumPy addresses this problem

http://www.scipy.org/Tentative_NumPy_Tutorial#head-d3f8e5fe9b903f3c3b2a5c0dfceb60d71602cf93

>>> a = array( [2,3,4] )
>>> a
array([2, 3, 4])
>>> type(a)
<type 'numpy.ndarray'>

But if you want to use the Python native lists as a matrix the following helper methods can become handy:

import copy

def Create(dimensions, item):
    for dimension in dimensions:
        item = map(copy.copy, [item] * dimension)
    return item
def Get(matrix, position):
    for index in position:
        matrix = matrix[index]
    return matrix
def Set(matrix, position, value):
    for index in position[:-1]:
        matrix = matrix[index]
    matrix[position[-1]] = value
Jader Dias
+9  A: 

In case a matrix is actually what you are looking for, consider the numpy package.

http://docs.scipy.org/doc/numpy/reference/generated/numpy.zeros.html#numpy.zeros

This will give you a 3x3x3 array of zeros:

numpy.zeros((3,3,3)) 

You also benefit from the convenience features of a module built for scientific computing.

Chris Cameron
This doesn't work. It should be numpy.zeros((3, 3, 3))
Zach Bialecki
@Cytokine corrected
Jader Dias
Hah, I swear the tuple was there when I typed it... Thanks Jader!
Chris Cameron
+1  A: 

List comprehensions are just syntactic sugar for adding expressiveness to list initialization; in your case, I would not use them at all, and go for a simple nested loop.

On a completely different level: do you think the n-dimensional array of NumPy could be a better approach?
Although you can use lists to implement multi-dimensional matrices, I think they are not the best tool for that goal.

Roberto Liffredo
A: 

This seems to be what you want:

def three_dimension_list(x,y,z):
return [[[0]*x]*y]*z
Matthew Mitchell
Sorry, but that is just as wrong as your other answer.
nikow
A: 

Or use the nest function defined here, combined with repeat(0) from the itertools module:

nest(itertools.repeat(0),[3,3,3])
Sander Evers