I am trying to create a 2d matrix so that each cell contains a list of strings. Matrix dimensions are known before the creation and I need to have access to any element from
Hey guys not sure if this is helpful or not but this is how I generated a 2d list with python3.4 hope this is helpful
list=[]
list1=[]
list2=[]
list3=[]
answer1='yes'
answer2='yes'
answer3='yes'
while answer1=='yes':
item1=input("Please input a list element for your first list:")
answer1=input("Do you want to continue:")
list1.append(item1)
while answer2=='yes':
item2=input("Please input a list element for your second list:")
answer2=input("Do you want to continue:")
list2.append(item2)
while answer3=='yes':
item3=input("Please input a list element for your third list:")
answer3=input("Do you want to continue:")
list3.append(item3)
list.append(list1)
list.append(list2)
list.append(list3)
print(list)
Just as you wrote it:
>>> matrix = [["str1", "str2"], ["str3"], ["str4", "str5"]]
>>> matrix
[['str1', 'str2'], ['str3'], ['str4', 'str5']]
>>> matrix[0][1]
'str2'
>>> matrix[0][1] += "someText"
>>> matrix
[['str1', 'str2someText'], ['str3'], ['str4', 'str5']]
>>> matrix[0].extend(["str6"])
>>> matrix[0]
['str1', 'str2someText', 'str6']
Just think about 2D matrix as list of the lists. Other operations also work fine, for example,
>>> matrix[0].append('value')
>>> matrix[0]
[0, 0, 0, 0, 0, 'value']
>>> matrix[0].pop()
'value'
>>>
You can either do it with the basic:
matrix = [
[["s1","s2"], ["s3"]],
[["s4"], ["s5"]]
]
or you can do it very genericially
from collections import defaultdict
m = defaultdict(lambda : defaultdict(list))
m[0][0].append('s1')
In the defaultdict case you have a arbitrary matrix that you can use, any size and all the elements are arrays, to be manipulated accordingly.
First of all, what you describe is actually a 3 dimensional matrix since each 'cell' also has a dimension whose kth
element of the jth
column of the ith
row could be accessed via matrix[i][j][k]
.
Regardless, if you'd like to preallocate a 2X2 matrix with every cell initialized to an empty list, this function will do it for you:
def alloc_matrix2d(W, H):
""" Pre-allocate a 2D matrix of empty lists. """
return [ [ [] for i in range(W) ] for j in range(H) ]
However you might think it's not working because I noticed that you said that you would like to have a 2X2 matrix like this:
[
[
['A','B'], ['C']
],
[
['d'], ['e','f','f']
]
]
and be able to use "traditional matrix access operations" to do this to it:
(Matrix[2][2]).extend('d')
Problem is that won't work even for the matrix shown and still wouldn't for one preallocated to 2X2 since both the row and column dimensions are out of range in either case. In Python all sequences are indexed from zero, so valid indices for a matrix with two rows of two elements each are [0][0]
, [0][1]
, [1][0]
, and [1][1]
(ignoring possible negative indices which have a special meaning in Python). So using Matrix[2][2]
is an attempt to access the third column of the third row of the matrix which don't exist and wouldn't even in a preallocated one with dimensions of 2X2.
Everything would be fine if you changed that statement to something like this using one of the valid pairs of index values (and with unnecessary parentheses removed):
Matrix[1][1].extend('d')
since it would not raise an IndexError
and instead would result in the 2X2 matrix becoming:
[
[
['A', 'B'], ['C']
],
[
['d'], ['e', 'f', 'f', 'd']
]
]
Bonus Utility
You didn't ask for one, but here's a handy function I wrote to help printing out arbitrarily sized 2D matrices of any type (represented as nested lists
):
def repr_matrix2d(name, matrix):
lines = ['{} = ['.format(name)]
rows = []
for row in range(len(matrix)):
itemreprs = [repr(matrix[row][col]) for col in range(len(matrix[row]))]
rows.append('\n [\n {}\n ]'.format(', '.join(itemreprs)))
lines.append('{}\n]'.format(','.join(rows)))
return ''.join(lines)
Hope this helps.
Here's some minimal example that extends 2d list of lists:
my_list = [ [ [1] for x in range(4) ] for j in range(2) ]
print('initial list is ', my_list)
my_list[0][1].append(9)
print('list after extension is ', my_list)
and the results are
initial list is [[[1], [1], [1], [1]], [[1], [1], [1], [1]]]
list after extension is [[[1], [1, 9], [1], [1]], [[1], [1], [1], [1]]]
One option is to write your own class, where you overload the [] operator. Take a look for that in here: http://www.penzilla.net/tutorials/python/classes/ . Acessing a 2d elment in 1d is y * rowSize + x. Extending the elements by writing an append function, which would use append rowSize times.
If you want to create a 2d matrix and you need to preallocate than, you could do the following:
x,y = 3,3
A = [ [None]*x for i in range(y) ]
You can replace None with the value you want. And you can use .extend to add additional values.