Pythonic way to create a 2d array? - python

I want to create a 2d array of integer values initially set to 0.
This is how I would think to do it:
grid = [[0] * width] * height
But this just creates each row as a reference to the original, so doing something like
grid[0][1] = 1
will modify all of the grid[n][1] values.
This is my solution:
grid = [[0 for x in range(width)] for y in range(height)]
It feels wrong, is there a better more pythonic way to do this?
EDIT:
Bonus question, if the grid size is never going to change and will only contain integers should I use something like a tuple or array.array instead?

Since numbers are immutable, using * to create a list should be fine. So, the 2D list initialization can be done like this
[[0] * width for y in range(height)]

You could use numpy.zeros:
import numpy as np
numpy.zeros(height, width)
If it has to be integer use as option dtype=numpy.int8

Here is what I used.
def generate_board(n): #Randomly creates a list with n lists in it, and n random numbers
#in each mini list
list = []
for i in range(0, n):
list.append([])
for j in range(0, n):
list[i].append(random.randint(0, 9))
return list
def print_board(board):
n = len(board) - 1
while n > -1:
print str(board[n]) + ' = ' + str(n)
n -= 1

Related

Pad both sides of 1D array while keeping edge indices

Given a 1D array x of size n and some index i where 0 <= x <= len(arr), I would like to be able to extract x[i] along with l neighboring elements to the left and l neighboring elements to the right, like this:
>>> i = 5
>>> l = 2
>>> x = np.arange(9,)
>>> def crop_array(arr):
'''do something'''
>>> crop_array(x)
array([2,3,4,5,6])
The thing is, I would like to keep all of these arrays the same size, so if i = 1 - l < 0, then I want to pad the array to yield something like array([0,1,2,3,4]). The would also hold true in cases where i + l > len(x), except the padding would be on the other side.
I'm trying to pad both sides of the array and then slice it:
def crop_array(arr, l, i):
x = np.zeroes(len(arr) + 2 * l)
x[l:len(x)-l] = arr
but I'm not sure how I can make it so that I can reindex the array to get the elements I want.
Whoops, figured it out. I can just add l to i.

How to creat a matrix(array)of size 10 and set all value is 0. With clash(i,j)=0

N = 10
# input the number of columns
M = 10
# initializing the matrix
res = [ [ i*j for i in range(N) ] for j in range(M) ]
clash(i,j)=0
# printing in multiple lines
print("Multiline representation")
for i in range(N):
for j in range(M):
#matrix.append(["0"]*100)
print(res[i][j] ,end =" ")
print("")
There exist an error shows can't assign to function call on clash
(i,j)=0.Thus, i really need help!
Maybe by creating list?
matrix = [[0] * 10] * 10
Image
I believe numpy is much more suited for this
import numpy as np
array = np.zeros((i,j))
EDIT:
To set values use:
array[y][x] = value

Creating an identity matrix of size 16x16 using 2 for loops with ranges (1,5)

I am trying to create a 16x16 identity matrix in python by using nested for loops.
import numpy as np
total = []
for i in range(1,5):
for j in range(1,5):
row = 16*[0]
total.append(row)
mat = np.matrix(total)
How do I modify this to get an identity matrix? The ranges cannot be changed.
You can follow this. It is done here simply. Note that there are many ways to do this. You can also follow the second way I uploaded below.
import numpy as np
total =[]
for i in range(1,17):
row=[]
for j in range(1,17):
if i==j:
row.append(1)
else:
row.append(0)
total.append(row)
mat = np.array(total)
Alternative way:
matrix = np.asmatrix(np.eye(16), dtype=int)
Actually it is much easier to create your matrix as:
mat = np.asmatrix(np.eye(16), dtype=int)
But if you insist on usage of 2 nested loops, with ranges (1, 5),
you can do it as follows:
total = []
row = [1] + [0] * 15
for _ in range(1,5):
for _ in range(1,5):
total.append(row)
row = np.roll(row, 1).tolist()
mat = np.matrix(total)
Note that each loop is executed actually 4 times, so the total number
of executions is just 16.
Even i and j, which you used in your code, are not needed
(they are never used), so I put _ instead of them.

python inverse matrix without numpy

I can't figure it out what's wrong with my code, it's rly frustrating.
I have to make inverse matrix function, what I thought I've done. I don't know why it doesn't work. The problem is probably in line with stars, after this step my matrix named mat is changed to identity matrix, but why? Before stars it prints my mat matrix normaly which I gave to function, but after stars it's a identity matrix, I don't understand why it happend. Here's what I have:
def identity_matrix_convertion(m):
x = m[:]
for i in range(len(x)):
for j in range(len(x[0])):
if i == j:
x[i][j] = 1
else:
x[i][j] = 0
return x
def inverse_matrix(mat):
n = len(mat)
am = mat[:]
show_matrix(mat)
**i = identity_matrix_convertion(am)**
show_matrix(mat)
im = i[:]
ind = list(range(n))
print(len(mat))
if determinant(mat) == 0:
print("This matrix doesn't have an inverse.")
if len(mat) == len(mat[0]):
for i in range(n):
scal = 1.0 / am[i][i]
for j in range(n):
am[i][j] *= scal
im[i][j] *= scal
for k in ind[0:i] + ind[i + 1:]:
current_scal = am[k][i]
for l in range(n):
am[k][l] = am[k][l] - current_scal * am[i][j]
im[k][l] = im[k][l] - current_scal * im[i][j]
return im
so after line **i = identity_matrix_convertion(am)** my mat matrix is changed into identity matrix, but why?
The result is:
1.0 2.0 3.0
2.0 1.0 3.0
4.0 3.0 2.0
The result is:
1 0 0
0 1 0
0 0 1
Instead of saying x = m[:] in the identity_matrix_convertion() function, you should add the following snippet:
x = []
for i in m:
arr = [a for a in i]
x.append(arr)
x = m[:] is still referencing m instead of just making a copy.
Following up on #NumberC's answer, the x = m[:] does make a copy, but only a shallow copy. The copied list will contain references to internal lists of the other list, and so manipulating those lists within x cause change in m too. This is because we represent the 2D matrix as list of lists. If someone would reorder the lists in m (so not the items within the lists but just the pure order of the lists within m) the order would stay the same in the x copy. However any change within the list of the lists is mutating the other too. I hope this is not confusing, List changes unexpectedly after assignment. Why is this and how can I prevent it? has some figures.
Since we don't have to scare away from [:] we can still say:
x = new_list = [y[:] for y in m]
Or even better: we can use the built-in copy module (available everywhere):
import copy
x = copy.deepcopy(m)
See also: Copying nested lists in Python

2d array throwing "list indices must be integers, not list" python

I'm trying to make a 2d list in python, i.e. a 2d array, for a game in pygame. The idea is that a new square will be drawn until I have a grid of squares. This is the code I have so far:
grid = []
width = 10
height = 10
x = -width
y = -height
index = 0
while index < height:
grid.append([])
index += 1
for i in grid:
y += height
for j in grid[i]:
x += width
grid_square = Grid_square(x,y)
grid[i].append(grid_square)
the problem is when I run it I get typeError: list indices must be integers, not list on the line "for j in grid[i]". This sort of thing would work fine in javascript, but I've never made a 2d list in python before. How can I iterate through a 2d list and make a grid of my Grid_square objects in a more elegant way that doesn't throw any errors?
You need for j in i, not for j in grid[i]. i is already a list - no need for indexing.
To get the structure you're looking for, you can replace the entire code snippet in your question with this:
width = 10
height = 10
grid = [[Grid_square(column*height, row*width) for column in range(10)] for row in range(10)]
This is equivalent to the following nested loops:
width = 10
height = 10
grid = []
for row in range(10):
c = []
for column in range(10):
c.append(Grid_square(column*height, row*width))
grid.append(c)

Categories