Create 3D array using Python

I would like to create a 3D array in Python (2.7) to use like this:

distance[i][j][k] 

And the sizes of the array should be the size of a variable I have. (nnn)

I tried using:

distance = [[[]*n]*n] 

but that didn't seem to work.

I can only use the default libraries, and the method of multiplying (i.e.,[[0]*n]*n) wont work because they are linked to the same pointer and I need all of the values to be individual

1

10 Answers

You should use a list comprehension:

>>> import pprint >>> n = 3 >>> distance = [[[0 for k in xrange(n)] for j in xrange(n)] for i in xrange(n)] >>> pprint.pprint(distance) [[[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]]] >>> distance[0][1] [0, 0, 0] >>> distance[0][1][2] 0 

You could have produced a data structure with a statement that looked like the one you tried, but it would have had side effects since the inner lists are copy-by-reference:

>>> distance=[[[0]*n]*n]*n >>> pprint.pprint(distance) [[[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]]] >>> distance[0][0][0] = 1 >>> pprint.pprint(distance) [[[1, 0, 0], [1, 0, 0], [1, 0, 0]], [[1, 0, 0], [1, 0, 0], [1, 0, 0]], [[1, 0, 0], [1, 0, 0], [1, 0, 0]]] 
2

numpy.arrays are designed just for this case:

 numpy.zeros((i,j,k)) 

will give you an array of dimensions ijk, filled with zeroes.

depending what you need it for, numpy may be the right library for your needs.

4

The right way would be

[[[0 for _ in range(n)] for _ in range(n)] for _ in range(n)] 

(What you're trying to do should be written like (for NxNxN)

[[[0]*n]*n]*n 

but that is not correct, see @Adaman comment why).

1
d3 = [[[0 for col in range(4)]for row in range(4)] for x in range(6)] d3[1][2][1] = 144 d3[4][3][0] = 3.12 for x in range(len(d3)): print d3[x] [[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, 144, 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, 0, 0]] [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [3.12, 0, 0, 0]] [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] 
0
""" Create 3D array for given dimensions - (x, y, z) @author: Naimish Agarwal """ def three_d_array(value, *dim): """ Create 3D-array :param dim: a tuple of dimensions - (x, y, z) :param value: value with which 3D-array is to be filled :return: 3D-array """ return [[[value for _ in xrange(dim[2])] for _ in xrange(dim[1])] for _ in xrange(dim[0])] if __name__ == "__main__": array = three_d_array(False, *(2, 3, 1)) x = len(array) y = len(array[0]) z = len(array[0][0]) print x, y, z array[0][0][0] = True array[1][1][0] = True print array 

Prefer to use numpy.ndarray for multi-dimensional arrays.

You can also use a nested for loop like shown below

n = 3 arr = [] for x in range(n): arr.append([]) for y in range(n): arr[x].append([]) for z in range(n): arr[x][y].append(0) print(arr) 

There are many ways to address your problem.

  1. First one as accepted answer by @robert. Here is the generalised solution for it:
def multi_dimensional_list(value, *args): #args dimensions as many you like. EG: [*args = 4,3,2 => x=4, y=3, z=2] #value can only be of immutable type. So, don't pass a list here. Acceptable value = 0, -1, 'X', etc. if len(args) > 1: return [ multi_dimensional_list(value, *args[1:]) for col in range(args[0])] elif len(args) == 1: #base case of recursion return [ value for col in range(args[0])] else: #edge case when no values of dimensions is specified. return None 

Eg:

>>> multi_dimensional_list(-1, 3, 4) #2D list [[-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1]] >>> multi_dimensional_list(-1, 4, 3, 2) #3D list [[[-1, -1], [-1, -1], [-1, -1]], [[-1, -1], [-1, -1], [-1, -1]], [[-1, -1], [-1, -1], [-1, -1]], [[-1, -1], [-1, -1], [-1, -1]]] >>> multi_dimensional_list(-1, 2, 3, 2, 2 ) #4D list [[[[-1, -1], [-1, -1]], [[-1, -1], [-1, -1]], [[-1, -1], [-1, -1]]], [[[-1, -1], [-1, -1]], [[-1, -1], [-1, -1]], [[-1, -1], [-1, -1]]]] 

P.S If you are keen to do validation for correct values for args i.e. only natural numbers, then you can write a wrapper function before calling this function.

  1. Secondly, any multidimensional dimensional array can be written as single dimension array. This means you don't need a multidimensional array. Here are the function for indexes conversion:
def convert_single_to_multi(value, max_dim): dim_count = len(max_dim) values = [0]*dim_count for i in range(dim_count-1, -1, -1): #reverse iteration values[i] = value%max_dim[i] value /= max_dim[i] return values def convert_multi_to_single(values, max_dim): dim_count = len(max_dim) value = 0 length_of_dimension = 1 for i in range(dim_count-1, -1, -1): #reverse iteration value += values[i]*length_of_dimension length_of_dimension *= max_dim[i] return value 

Since, these functions are inverse of each other, here is the output:

>>> convert_single_to_multi(convert_multi_to_single([1,4,6,7],[23,45,32,14]),[23,45,32,14]) [1, 4, 6, 7] >>> convert_multi_to_single(convert_single_to_multi(21343,[23,45,32,14]),[23,45,32,14]) 21343 
  1. If you are concerned about performance issues then you can use some libraries like pandas, numpy, etc.
n1=np.arange(90).reshape((3,3,-1)) print(n1) print(n1.shape) 
def n_arr(n, default=0, size=1): if n is 0: return default return [n_arr(n-1, default, size) for _ in range(size)] arr = n_arr(3, 42, 3) assert arr[2][2][2], 42 

If you insist on everything initializing as empty, you need an extra set of brackets on the inside ([[]] instead of [], since this is "a list containing 1 empty list to be duplicated" as opposed to "a list containing nothing to duplicate"):

distance=[[[[]]*n]*n]*n 
2

You Might Also Like