Python multiple dimension arrays [duplicate] - python

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to initialize a two-dimensional array in Python?
In solving a simple problem regarding a two dimensional array I came across a solution on this site that explained how to declare one in Python using the overload operator.
Example:
Myarray = [[0]*3]*3
this would produce the following array (list)
[[0,0,0],[0,0,0],[0,0,0]]
This seems fine until you use it:
if you assign an element for example:
Myarray [0][0] = 1
you get the unexpected output:
[[1,0, 0],[1,0,0] , [1,0,0]]
In effect assigning Myarray [1][0] and Myarray[2][0] at the same time
My solution:
Myarray = [[][][]]
for i in range(0,3):
for j in range (0,3):
Myarray[i].append(0)
This solution works as intended:
Marray[0][1] = 1
gives you
[[1,0, 0],[0,0,0] , [0,0,0]]
Is there a simpler way to do this? This was a solution to an A level Cambridge question and seems too long winded for students compared to other languages.

With vanilla Python, you could use this, a nested list comprehension
>>> m = [[0 for y in range(3)] for x in range(3)]
>>> m
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
Unlike the multiplied list you showed in your example, it has the desired behavior
>>> m[1][0] = 99
>>> m
[[0, 0, 0], [99, 0, 0], [0, 0, 0]]
However, for serious use of multidimensional arrays and/or numerical programming, I'd suggest you use Numpy arrays.

Related

Indexed array filled incorrectly [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 3 years ago.
I just started programming with Python and I have a question concerning 2D arrays.
I need to create a matrix (numpy forbidden) of a certain size from av[1] and save it so that I can multiply it with another one later on.
The logical thing for me was:
1- Get the length of av[1]; 2- Transform the av[1][] to it's ASCII equivalent with ord and finally 3- Insert that value into a list called key_matrix.
The matrix needs to be the smallest size possible and in a "square form", so I calculate the smallest square containing the len of av[1] ( called matrix_size ) and then I initialize my array like this:
key_matrix = [[0] * matrix_size] * matrix_size;
Like that I get my square matrix filled with 0.
If matrix_size = 3 for example I get:
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
Now the strange part is (and also the part that I'm stuck on) the following, I use
index1 = 0;
index2 = 0;
key_matrix[index1][index2] = ord(sys.argv[1][0]);
print(key_matrix);
to fill only the 1st element of the 1st line.
While the result should be:
[[97, 0, 0], [0, 0, 0], [0, 0, 0]]
I get:
[[97, 0, 0], [97, 0, 0], [97, 0, 0]]
Me and my friends really cant seem to figure out the reason why it does this, any help is welcome!
Thank you all for reading :)
The memory address of the lists are the same when you write [[0] * matrix_size] * matrix_size, it basically reuses the memory address of the first [0] * matrix_size array as the same reference for multiple times for other lists. Since these lists are not independent from memory address perspective, we would have issue modifing only one of the list. You can do below as a quick fix for the issue:
>>> key_matrix2 = [[0] *3 for i in range(matrix_size)]
>>> key_matrix2
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> key_matrix2[0][1] = 2
>>> key_matrix2
[[0, 2, 0], [0, 0, 0], [0, 0, 0]]

Indexing of lists within a list in python [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Python list multiplication: [[...]]*3 makes 3 lists which mirror each other when modified [duplicate]
(4 answers)
Closed 6 years ago.
I have a list of lists in python.
z=[[0]*6]*7
Since all elements are 0. But now if i want to change an individual element within a list e.g
z[0][0]=2
This should change the first element of the first list. But it actually changes the first element of all elements. This is so illogical to me.
Can some one help.
[2, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 0, 0]]
That's a classical "programmer's trap" in python.
l = [ 0 ] * 6
creates a list containing six times a reference to the same python object, here, the numerical constant 0.
Now, setting
l[0] = 1
will replace the first reference to the const 0 object by a reference to another object, the const 1 object.
Now, let's look at
z=[[0]*6]*7
This first creates a list containing six references to the const 0 object, and then it creates a list containing seven references to that single six-element list.
Now,
z[0]
will give you the first element from z, which is simply the same as all the six other elements.
Proof:
print id(z[0]) == id(z[1])
different objects have different IDs.
So you never actually made a list of different lists, but just the same list all over.
You can actually create different sublists and put them into one by doing something like
z = [ [0]*6 for _ in range(7) ]
However, I get the feeling you actually might want to use matrices – if that's really the case, numpy's ndarray is what you're after, because:
import numpy
z = numpy.ndarray((7,6))
actually gives you a matrix with 42 numeric elements.

How do I form a matrix identity? [duplicate]

This question already has answers here:
Trying to understand nested loops, identity matrix
(4 answers)
Closed 8 years ago.
What I'm trying to accomplish here is to generate a matrix of size n x n. Whatever the matrix is, I have to fill in the number 1 from the top-left corner to the bottom-right corner and 0 everywhere else.
def identity(m):
new_identity = []
old_identity = m
for i in range(len(old_identity)):
new_identity.append(old_list[1])
return new_identity
For example, if the matrix was 3 then the expected result would be:
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
Or to make it easier to visualize:
[[1, 0, 0],
[0, 1, 0],
[0, 0, 1]]
where n is the size of the identity to make
def identity(n):
return [[1 if i==j else 0 for j in range(n)] for i in range(n)]
This one might not be the most pythonic, but it's faster than the other solution.
def identity(m):
result = []
for i in range(m):
row = [0]*m
row[i] = 1
result.append(row)
return result
On my machine, for a 500x500 matrix, my function takes 3.13 ms to execute, while the python list comprehension solution (that makes m² comparisons) takes 47.48 ms to complete.
Of course, you should use xrange instead of range if you're using python 2.x

python how to change value of elements of sublists? [duplicate]

This question already has answers here:
Creating lists of lists in a pythonic way
(8 answers)
Closed 9 years ago.
I have the following code:
matrix = [[0] * 3] * 3
matrix[0][0] = 2
I want to get the following result:
[[2, 0, 0], [0, 0, 0], [0, 0, 0]]
However it changes the first element of each sublist and returns this list:
[[2, 0, 0], [2, 0, 0], [2, 0, 0]]
If I define matrix as follow:
matrix = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
then it works.
Could anyone tell me please, why it happens and how could solve this problem?
Thanks
This is happening because [[0] * 3] * 3 is actually creating an array of 3 of the same object (the [0] * 3 array). One way of looking at it is that the inner array is created once and copied. An alternative would be to use [[0] * 3 for x in xrange(3)], as this executes [0] * 3 each iteration in list comprehension, creating a new array each time.
Here's your problem, matrix, in this example, is basically identical to:
>>> a = [0,0,0]
>>> matrix1 = [a,a,a]
that means when you do matrix1[0][0] = 2, what Python does is follow its pointer located at the first index of matrix1, which points to object a, then looks at the pointer located at the first index of a, which reads 0, then changes that to 2. Then when you ask it to evaluate matrix1, it looks up a three times and finds [2,0,0] each time.
Sean had a good solution above mine, using list comprehensions to force new objects instead of adding pointers for objects that already exist. That may serve you better :)
Python assigns by pointer rather than value* which sometimes leads to undesirable results such as this one. Here is a tutorial that explains what is really happening: http://www.python-course.eu/variables.php Here is one possible fix http://www.python-course.eu/deep_copy.php
*(as has been pointed out this is not quite right, however it similar in result to what happens in other languages like C which I'm more familiar with if you passed a pointer to a variable rather than a copy of the value of the variable.)

Syntax in Python (.T)

In the help resource for the multivariate normal sampling function in SciPy, they give the following example:
x,y = np.random.multivariate_normal(mean,cov,5000).T
My question is rather basic: what does the final .T actually do?
Thanks a lot, I know it is fairly simple, but it is hard to look in Google for ".T".
The .T accesses the attribute T of the object, which happens to be a NumPy array. The T attribute is the transpose of the array, see the documentation.
Apparently you are creating random coordinates in the plane. The output of multivariate_normal() might look like this:
>>> np.random.multivariate_normal([0, 0], [[1, 0], [0, 1]], 5)
array([[ 0.59589335, 0.97741328],
[-0.58597307, 0.56733234],
[-0.69164572, 0.17840394],
[-0.24992978, -2.57494471],
[ 0.38896689, 0.82221377]])
The transpose of this matrix is:
array([[ 0.59589335, -0.58597307, -0.69164572, -0.24992978, 0.38896689],
[ 0.97741328, 0.56733234, 0.17840394, -2.57494471, 0.82221377]])
which can be conveniently separated in x and y parts by sequence unpacking.
.T is just np.transpose().
Best of luck
Example
import numpy as np
a = [[1, 2, 3]]
b = np.array(a).T # ndarray.T The transposed array. [[1,2,3]] -> [[1][2][3]]
print("a=", a, "\nb=", b)
for i in range(3):
print(" a=", a[0][i]) # prints 1 2 3
for i in range(3):
print(" b=", b[i][0]) # prints 1 2 3

Categories

Resources