Declaring and populating 2D array in python - python

I want to declare and populate a 2d array in python as follow:
def randomNo():
rn = randint(0, 4)
return rn
def populateStatus():
status = []
status.append([])
for x in range (0,4):
for y in range (0,4):
status[x].append(randomNo())
But I always get IndexError: list index out of range exception. Any ideas?

More "modern python" way of doing things.
[[ randint(0,4) for x in range(0,4)] for y in range(0,4)]
Its simply a pair of nested list comprehensions.

The only time when you add 'rows' to the status array is before the outer for loop.
So - status[0] exists but status[1] does not.
you need to move status.append([]) to be inside the outer for loop and then it will create a new 'row' before you try to populate it.

You haven't increase the number of rows in status for every value of x
for x in range(0,4):
status.append([])
for y in range(0,4):
status[x].append(randomNo())

If you're question is about generating an array of random integers, the numpy module can be useful:
import numpy as np
np.random.randint(0,4, size=(4,4))
This yields directly
array([[3, 0, 1, 1],
[0, 1, 1, 2],
[2, 0, 3, 2],
[0, 1, 2, 2]])

Related

How to add a 1 into a list based on the values of another list, which give the position of where 1 should go

I have two lists:
a = [1,4,5]
x = [0,0,0,0,0,0,0,0,0,0]
I am stuck on making it so that it could look like this:
x= [0,1,0,0,1,1,0,0,0,0,0]
So that the number 1 is added to list x based on the value of list a, where the list values in a determine the position of where 1 should go. I am not sure if that makes much sense but it would help a lot.
You can use a for loop to iterate through list a and set the indexes of list x of its values to 1. So for example:
a = [1, 4, 5]
x = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
for index in a: # Iterating through the list a
x[index] = 1 # Setting the values to 1
print(x)
Alternative way,
using numpy fast and efficient
np_x = np.array(x)
np_x[a]=1

Pick random integers from list elements of same index and generate a list

I have two lists a & b and I need to pick a random element of a[i] and b[i] and generate z.
a = [1, 0, 1, 1, 0, 1]
b = [1, 1, 0, 1, 0, 0]
z = [1, 0, 1, 1, 0, 0]
I used the below mentioned code:
import random
z = []
for i in range(6):
value = random(a[i],b[i])
z.append(value)
print z
and I get the following error:
TypeError: 'module' object is not callable
You can use random.choice (docs here).
Return a random element from the non-empty sequence seq.
It selects one value from a list of values. For each iteration, you can just create a list of a[i] and b[i].
for i in range(6):
value = random.choice([a[i],b[i]])
z.append(value)
print( z)
# [1, 1, 1, 1, 0, 0]
Another option is to use random.sample where k=1 here and [a[i],b[i]] is the population as following
Return a k length list of unique elements chosen from the population sequence or set
value = random.sample([a[i],b[i]], 1)
z.append(value[0])
Here value[0] is used because value is a list containing single element so by using [0] you get that element without the list.
You're calling random as if it's a function, when in fact it's a module. You need to use random.choice to choose one of the two options:
value = random.choice([a[i],b[i]])
First off all you have to import random module.
import random
Then you can call any of its method:
random.random()
Furthermore you have should choose random.choice():
value = random.sample([a[i],b[i]], 1)

Create array containing list of lists of n repeated items in Python

I try to find a faster way to create such a list:
import numpy as np
values = [0,1,2]
repeat = [3,4,2]
list = np.empty(0, dtype=int)
for i in range(len(values)):
list = np.append(list, np.full(repeat[i], values[i]))
print list
returns
[0 0 0 1 1 1 1 2 2]
Any idea? Thanks
You can save a lot of time using native python lists instead of numpy arrays. When I ran your code using the timeit module, it took 16.87 seconds. The following code took 0.87.
list = []
for val, rep in zip(values, repeat):
list.extend([val]*rep)
If you then convert list to a numpy array using list = np.array(list), that time goes up to 2.09 seconds.
Of course, because numpy is optimized for large amounts of data, this may not hold for very long lists of values with large numbers of repeats. In this case, one alternative would be to do you memory allocation all at the same time, instead of continually lengthening the array (which I believe covertly causes a copy to made, which is slow). The example below completes in 4.44 seconds.
list = np.empty(sum(repeat), dtype=int) #allocate the full length
i=0 #start the index at 0
for val, rep in zip (values, repeat):
list[i:i+rep] = [val]*rep #replace the slice
i+=rep #update the index
You can try this. Multiply lists of values by lengths for each pair of values and lengths.
You will get list of lists
L = [[i]*j for i, j in zip(values, repeat)]
print(L)
returns
[[0, 0, 0], [1, 1, 1, 1], [2, 2]]
Than make a flat list
flat_L = [item for sublist in L for item in sublist]
print(flat_L)
[0, 0, 0, 1, 1, 1, 1, 2, 2]
I would do like this:
a=[1,2,3]
b=[2,4,3]
x=[[y]*cnt_b for cnt_b,y in zip(b,a)]
Output:
[[1,1],[2,2,2,2],[3,3,3]]
In [8]: [i for i, j in zip(values, repeat) for _ in range(j)]
Out[8]: [0, 0, 0, 1, 1, 1, 1, 2, 2]
Here, we are zipping values and repeat together with zip to have one to one correspondence between them (like [(0, 3), (1, 4), (2, 2)]). Now, in the list comprehension I'm inserting i or values and looping them over range of j to repeat it jth times.

Trying to create identical sublists of variable length within function, but be able to edit them individually

I am trying to take a matrix presented in a .txt file and put it into a list. For example a 2x2 matrix would be in a list with the first sublist being the first row and the second sublist being the second row [[a,b],[c,d]]. I was trying to create a matrix list of a certain height by width and fill every value with a 0 and then update a small number of 0s to actual values.
m is a dictionary created from the txt file that looks like this:
{(2, 2): 5, (1, 2): 4, (0, 1): 2, (0, 0): 1, (1, 1): 3, (2, 3): 6}
r is the number of rows for the matrix, indicated in the text file. In this case r is 3
c is the number of columns. c is 4
s is a string for the name of the matrix that will be printed
def print_matrix(m,r,c,s):
w = sorted(m)
value_list = []
matrix_list = []
for i in range(c-1):
value_list.append(0)
for i in range(r):
matrix_list.append(value_list)
for i in w:
matrix_list[i[0]][i[1]] = m[i]
print(matrix_list)
After reading this topic: Changing an element in one list changes multiple lists ..?. I realize that when I try to edit the list of full of zeroes it changes a value for all rows, not just one row because the sublists are identical. How can I got about creating unique sublist that can be uniquely edited but preserve the ability for the list to have unique number of sublists, and sublist length to correspond to rows and columns?
You are appending the same list instance (value_list) into matrix_list multiple times. This is why when you tried to update a single entry, you updated the value of all sublists at once.
In order to make sure the sublists are different list instances, you'll need to create a new list for each sublist. So if you were do it as a for loop as you did, it would be a nested for loop like so:
# Create a row for each row count
for i in range(r):
# Create a brand new row
value_list = []
for i in range(c-1):
value_list.append(0)
# Push the new row to the matrix
matrix_list.append(value_list)
However, using your link I have a more condensed representation:
matrix_list = [[0] * (c-1) for k in range(r)]
Put together it would like so:
def print_matrix(m,r,c,s):
w = sorted(m)
matrix_list = [[0] * (c-1) for k in range(r)]
for i in w:
matrix_list[i[0]][i[1]] = m[i]
print(matrix_list)
This throws a index out of range error at it's current form, however that's a different problem. :)
You are running into an aliasing issue. The line
matrix_list.append(value_list)
appends not a copy of the value_list, but a reference to the value_list object. You can circumvent this in a number of ways. The easiest is to simply create a copy of the list when you append it. Using:
matrix_list.append(value_list.copy())
creates a new object, instead of just assigning a reference to an existing object.
Examples:
Here we see an example of aliasing the same list 3 times. When any of the aliases are updated, all of them are changed because they are all the same object.
matrix = []
x = [0,0,0]
for i in range(3):
matrix.append(x)
matrix
# returns
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
matrix[0][0] = 1
matrix
# returns
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
You can instead append a copy of the list, which forces a new object to be created at each row.
matrix = []
x = [0,0,0]
for i in range(3):
matrix.append(x.copy()) # create a copy
matrix
# returns
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
matrix[0][0] = 1
matrix
# returns
[[1, 0, 0], [0, 0, 0], [0, 0, 0]]
Only the first row is modified.

'int' object does not support item assignment

This is my code,and it appears a problem like the topic. i am a primary learner and i don't know where is the problem. could u help me fix the code and tell me which part of knowledge i need to review. thanks in advance.
x = int(raw_input("enter the value of x:"))
y = int(raw_input("enter the value of y:"))
i = 0
j = 0
array=[x*y]
for i in range(x):
array.append([0 for j in range(y)])
for i in range(x-1):
for j in range(y-1):
array[i][j]=i * j
print array
The problem is that you are creating a list of mixed types, integers and lists, and then trying to access the integer value as if it was a list.
Let's use a simple example:
x = 2
y = 3
i = 0
j = 0
array = [x*y]
Now, let's look at what array currently contains:
array
>> 6
Now we run your first for loop:
for i in range(x):
array.append([0 for j in range(y)])
And let's check the new value of array:
array
>> [6, [0, 0, 0], [0, 0, 0]]
So now we see that the first element of array is an integer. The remaining elements are all lists with three elements.
The error occurs in the first pass through your nested for loops. In the first pass, i and j are both zero.
array[0][0] = 0*0
>> TypeError: 'int' object does not support item assignment
Since array[0] is an integer, you can't use the second [0]. There is nothing there to get. So, like Ashalynd said, the array = x*y seems to be the problem.
Depending on what you really want to do, there could be many solutions. Let's assume you want the first element of your list to be a list of length y, with each value equal to x*y. Then replace array = [x*y] with:
array = [x*y for i in range(y)]
Try inspect your array.
array[2*3] will result in [6].
array.append([0 for j in range(3)]) will then result in [6,[0,0,0]], your first element is not an array.
There is in indent error with your for loops.
I think what you are trying to do is this:
array2=[]
for i in range(2):
array2.append([0 for j in range(3)])
Your syntax is so wrong. First of all if you store variables i=0, j=0 so why you use them in for loop? It doesn't make any sense.
Second, just debug it, put print (array) after the list.
if x=5 and y=5 ;
[25, [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]]
This is your array, and this line;
array[i][j]=i * j
Throwing error? Why? Because;
j=0
i=0
array[i]=25
array[i][j] = 2
So that's why you got error.Integers, which is 2 here, doesn't support item assignment. Try to fix your syntax.

Categories