How do I create a multidimensional list?

Q: I created a list of lists, but when I assign to an item, the entire column is changed.

A: You probably tried to make a multidimensional array like this:

A = [[None] * 2] * 3

This looks correct if you print it:

>>> A
[[None, None], [None, None], [None, None]]

But when you assign a value, it shows up in multiple places:

 >>> A[0][0] = 5
 >>> A
 [[5, None], [5, None], [5, None]]

The reason is that replicating a list with * doesn’t create copies, it only creates references to the existing objects. The *3 creates a list containing 3 references to the same list of length two. Changes to one row will show in all rows, which is almost certainly not what you want.

The suggested approach is to create a list of the desired length first and then fill in each element with a newly created list:

A = [None]*3
for i in range(3):
     A[i] = [None] * 2

This generates a list containing 3 different lists of length two. You can also use a list comprehension:

w,h = 2,3
A = [ [None]*w for i in range(h) ]

Or, you can use an extension that provides a matrix datatype; Numeric Python is the best known.

CATEGORY: programming

 

Comment:

'multidimensional' a bit off-putting for those with no Higher Maths? perhaps: 'How do I create a list of lists?' is better.

Posted by gerard

Comment:

# List comprehensions make this shorter, and can be done recursively:

def make2D(rows, cols, val=None):
   '''Returns a list of lists with specified number of rows and columns,
   initialized to val.'''
   return [[val for i in range(cols)] for j in range(rows)]

def multidimNone(*dims):
   '''Returns lists nested to the depth of the length of the parameter list.
   The innermost value is None.
   For example a = multidimNone(2, 4, 3) makes
      a[i][j][k] be None for i in range(2), j in range(4), k in range(3).'''
   if len(dims)  > 0:
       return [multidimNone(*dims[1:]) for i in range(dims[0])]

def multidim(val, *dims):
   '''Returns lists nested to the depth of the length of the parameter list
   after val.  The innermost value is val.  
   For example a = multidim(True, 2, 4, 3) makes
      a[i][j][k] be True for i in range(2), j in range(4), k in range(3).'''
   if len(dims)  > 0:
       return [multidim(val, *dims[1:]) for i in range(dims[0])]
   return val

print make2D(3, 2, '')
print multidimNone(3, 2)
print multidim(None, 3)
print multidim(True, 2, 3)
print multidim(0, 2, 2, 2)

Posted by AndyHarrington (2006-11-20)

A Django site. this page was rendered by a django application in 0.03s 2008-10-13 13:29:44.022066. hosted by webfaction.