Initialize 2D list - python

The follow codes didn't behave like I expected. Is this an incorrect way of initializing a 2D list filled with 0?
matrix = [[0] * 4] * 4
for row in matrix:
print(row)
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
matrix[0][0] = 1
for row in matrix:
print(row)
[1, 0, 0, 0]
[1, 0, 0, 0]
[1, 0, 0, 0]
[1, 0, 0, 0]

Use matrix = [[0 for i in range(4)] for j in range(4)] instead of matrix = [[0] * 4] * 4.
matrix = [[0 for i in range(4)] for j in range(4)]
matrix[0][0] = 1
for row in matrix:
print(row)
Output:
[1, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]

I actually ran into this problem a while ago! No, this isn't the correct way, at least for what you're expecting to happen.
The problem is that when you initialise this list, you create a list of references back to the first item, so when you modify it, you modify all of them, because in reality they all point to the same object in memory.
Instead of that you can do something like this:
x = 4
y = 4
matrix = [[0]*x for _ in range(y)]
With a result of:
[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
Then matrix[0][0] = 1 only sets the first element of the first list to 1.
You can extend this into 3D and beyond by simply adding a new layer of for __ in range(z) on the end and and wrapping it in more square brackets.

That is because the matrix is composed of a copy of the list [0,0,0,0].
This should work:
matrix = [[0 for i in range(4)] for j in range(4)]
matrix[0][0] = 1

In the general case you can make something like numpy.full (but for lists instead of arrays):
def full(shape, fill_value=0):
if len(shape) > 1:
return [full(shape[1:], fill_value) for _ in range(shape[0])]
else:
return [fill_value] * shape[0]
matrix = full((4, 4), 0)

Related

How to get list of lists of decreasing size from n to one

I want for a number n for there to be a nested list containing sublists that start off at length n and decrease to length one. If n was 4, the list would be:
[[0, 0, 0, 0], [0, 0, 0], [0, 0,], [0]]
Here's what I've tried:
triangle = []
for i in range(n):
for k in range(i):
triangle.append(0)
That just gave out for input n = 5:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
If you want to mantain your code form, you just use this function:
def get_triangle_list(n):
triangle_list = []
for i in range(n, 0, -1):
tmp_list = []
for k in range(i):
tmp_list.append(0)
triangle_list.append(tmp_list)
return triangle_list
print(get_triangle_list(4))
and output will be:
[[0, 0, 0, 0], [0, 0, 0], [0, 0], [0]]
But, as suggested by #Abhijit Sarkar, you can obtain the same output in smarter and more efficent way using list comprehension like
triangles = [[0] * x for x in range(n, 0, -1)]
n = 4
triangles = [[0] * x for x in range(n, 0, -1)]
print(triangles)

unable to slice numpy array input [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 11 months ago.
Improve this question
Expected output: [[1,0][1,0]]
Expected output: [[0,0][0,1]]
etc as the loops runs the range.
Error: at print statement. The loop is unable to run through the different indexes.
Error message only integer scalar arrays can be converted to a scalar index
import numpy as np
field = [[1, 0, 0, 0, 0, 1, 1, 0, 0, 0],
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0],
[1, 0, 1, 0, 1, 1, 1, 0, 1, 0],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
a2= np.array(field)
print(a2)
for i in list(range(10)):
for i in a2[i:i+2,i:i+2]:
print(a2[i:i+2,i:i+2])
If your goal is to print out a 2 by 2 matrix each time iterating through a2 from left to right and from top to bottom with step 1, the for loops should be like:
for i in range(9):
for j in range(9):
print(a2[i:i+2, j:j+2])
The outputs are:
[[1 0]
[1 0]]
[[0 0]
[0 1]]
[[0 0]
[1 0]]
[[0 0]
[0 0]]
[[0 1]
[0 0]]
etc.
That inside for loop should be for j in a2[i:i+2,i:i+2]: for it to work. it seems like
for i in range(10):
print(a2[i:i+2,i:i+2])
gives the same result
The error is saying that you have used i once then it is not an array to iterate through indexes. Why use two for loops? One for can do the job. Again no need to cast list on range.
for i in range(10):
print(a2[i:i+2,i:i+2])
You could iterate the matrix using a 2x2 window by using the shape of the matrix as a reference and a for loop to slide each dimension (x and y). This is a possible implementation:
for i in range(2, a2.shape[0]):
for j in range(2, a2.shape[1]):
print(a2[i-2:i,j-2:j])
Examine the values during the loops. This is basic python looping logic
In [310]: for i in range(2): # don't need list(range...)
...: print(i)
...: print(a2[i:i+2, i:i+2])
...: for i in a2[i:i+2, i:i+2]:
...: print(i)
...:
...:
0 # outer i
[[1 0] # the a2 window
[1 0]]
[1 0] # inner i, rows of that window
[1 0]
1 # outer i
[[0 1]
[0 1]]
[0 1]
[0 1]
It does not make sense to use the inner i as indices to a2. They are already arrays derived from a2. I don't know why beginners make this mistake
for i in alist:
alist[i] ... # i is an element of the list, not an index
With i being np.array([1,0]), this:
a2[i:i+2,i:i+2]
# a2[np.array([1,0]):np.array([3,2]), ....)
produces your error.
You used the first i in range correctly; why the change in the second?
Using a different iteration variable in the 2nd loop, and range again, produces are more logical nested iteration:
In [313]: for i in range(2):
...: print(i)
...: for j in range(2):
...: print(j)
...: print(a2[i:i+2, j:j+2])

Syntax Error:Creating An 2d List Filled With Zero

How Could I Initialize An 2D List Filled With Zeroes Without Any Additional Library/Module
here what is my attempt
table = [0 for i in range(amount + 1)[0 for j in range(len(coins))]]
it works in case of 1d list:Vector But Fails In Case Of 2d
Code:
table = [0 for i in range(amount + 1)]
O/P:
[0,0,0,0,0,0,0,0,0,0,0,0]
Code:
table = [0 for i in range(amount + 1)[0 for j in range(len(coins))]]
O/P:
Syntax Error
You are putting the inner comprehension part in the wrong position. Try:
rows, cols = 4, 5
table = [[0 for _ in range(cols)] for _ in range(rows)]
print(table)
# [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
First, _ here is nothing strange; it is just a dummy name, which we don't care. We could name it i for example, and nothing changes.
[... for _ in range(rows)] makes a list with length rows, with the items given by .... Now ... was [0 for _ in range(cols)], i.e., a list of zeros with length cols. Therefore, the result is a list (having length row) of [0, 0, ..., 0].

How to convert elements in a matrix into binary, and expand the matrix, and can reverse the operation

I am implementing a homomorphic encryption algorithm, and need to convert matrix like this
[[3 1 3]
[3 2 3]
[0 1 0]]
which splits a vector of integers ≤q into a log(q,2) longer vector of the bits of the integers,like:
[[0 1 1 0 0 1 0 1 1]
[0 1 1 0 1 0 0 1 1]
[0 0 0 0 0 1 0 0 0]]
Then it can be calculated as a normal matrix, and the final result can be converted from the binary to integer form.
I used some algorithms in numpy that convert matrix elements to binary, but I didn't achieve what I wanted.
You can do it with np.unpackbits.
>>> matrix = np.array([3,1,3,3,2,3,0,1,0],'uint8').reshape(3,-1)
>>> matrix
array([[3, 1, 3],
[3, 2, 3],
[0, 1, 0]], dtype=uint8)
>>> np.unpackbits(matrix.reshape(3,-1,1),2)[:,:,-3:].reshape(3,-1)
array([[0, 1, 1, 0, 0, 1, 0, 1, 1],
[0, 1, 1, 0, 1, 0, 0, 1, 1],
[0, 0, 0, 0, 0, 1, 0, 0, 0]], dtype=uint8)
Unpackbits will unpack your ints into 8 bits, but since you only seem to be interested in the 3 least significant bits, we unpack into a new axis, and use slicing [:,:,-3:] to strip out the padding zeros.
Here is one way of doing it:
import itertools
def expand_to_binary(my_list, q):
my_list = [list(('{0:0' + str(q) + 'b}').format(elem)) for elem in my_list]
my_list = [list(map(int, elem)) for elem in my_list]
my_list = list(itertools.chain(*my_list))
return my_list
x = [[3, 1, 3], [3, 2, 3], [0, 1, 0]]
x = [expand_to_binary(elem, 3) for elem in x]
q is the number of bits in every binary number. Although this is only the forward pass. Implementing the reverse part shouldn't be too difficult.
And this would be one way of implementing the reverse:
def decode_binary_to_int(my_list, q):
my_list = [list(map(str, my_list[i: i+q])) for i in range(0, len(my_list), q)]
my_list = [''.join(elem) for elem in my_list]
my_list = [int(elem, 2) for elem in my_list]
return my_list
x = [[0, 1, 1, 0, 0, 1, 0, 1, 1], [0, 1, 1, 0, 1, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 0, 0, 0]]
x = [decode_binary_to_int[elem] for elem in x]
Although this code works i should say it's probably not the most fastest way of implementing what you want, i just tried to provide an example for what you required.

How to initialise a 2D array in Python?

I've been given the pseudo-code:
for i= 1 to 3
for j = 1 to 3
board [i] [j] = 0
next j
next i
How would I create this in python?
(The idea is to create a 3 by 3 array with all of the elements set to 0 using a for loop).
If you really want to use for-loops:
>>> board = []
>>> for i in range(3):
... board.append([])
... for j in range(3):
... board[i].append(0)
...
>>> board
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
But Python makes this easier for you:
>>> board = [[0]*3 for _ in range(3)]
>>> board
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
arr=[[0,0,0] for i in range(3)] # create a list with 3 sublists containing [0,0,0]
arr
Out[1]: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
If you want an list with 5 sublists containing 4 0's:
In [29]: arr=[[0,0,0,0] for i in range(5)]
In [30]: arr
Out[30]:
[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
The range specifies how many sublists you want, ranges start at 0, so ranges 4 is 0,1,2,3,4.
gives you five [0,0,0,0]
Using the list comprehension is the same as:
arr=[]
for i in range(5):
arr.append([0,0,0,0])
arr
[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
If you want something closer to your pseudocode:
board = []
for i in range(3):
board.append([])
for j in range(3):
board[i].append(0)
numpy has something for this:
numpy.zeros((3,3))
You can use the style of pseudocode given or simply just use a python one liner
chess_board = [[x]*3 for _ in range(y)] --> list comprehension
or you can use the plain loop style of other languages like java. I prefer the one liner as it looks much nicer and cleaner.

Categories