Related
I'm fairly new to python and I am having trouble with an array.
I'm having a problem with a symmetric matrix. Being symmetric, X[0][6] is the same as X[6][0]. I'm looking to be able to append all non-zero values in said array into a list - however I don't want to include elements on the diagonal nor duplicates of elements on one of the sides of the diagonal. For example, I only want to append X[0][6] but not also X[6][0].
The 2D array is as follows:
X = [[9, 0, 0, 1, 0, 0, 6, 0],
[0, 4, 0, 0, 0, 0, 0, 1],
[0, 0, 9, 0, 4, 0, 0, 0],
[1, 0, 0, 3, 0, 0, 0, 1],
[0, 0, 4, 0, 8, 0, 0, 3],
[0, 0, 0, 0, 0, 4, 0, 0],
[6, 0, 0, 0, 0, 0, 9, 2],
[0, 1, 0, 1, 3, 0, 2, 8]]
I've attempted a for loop like so:
non_zero_entries = []
for i in X:
for j in i:
if j > 0:
non_zero_entries.append(j)
When I do this however, due to the nature of the symmetry of the array I get the following output which has not only the diagonal but also the duplicates within the matrix:
Out: [9, 1, 6, 4, 1, 9, 4, 1, 3, 1, 4, 8, 3, 4, 6, 9, 2, 1, 1, 3, 2, 8]
Ideally I need to be able to transform my matrix to look like this so that the diagonal and the other side of becomes 0.
ideal_X = [[0, 0, 0, 1, 0, 0, 6, 0],
[0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 4, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 3],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2],
[0, 0, 0, 0, 0, 0, 0, 0]]
This would give the output that I require:
Out: [1, 6, 1, 4, 1, 3, 2]
How would I either transform my matrix into the one I've provided, or is there a simpler way to get my desired output with the initial matrix?
You have the right idea in writing two nested for loops to iterate through the elements of your matrix. The outer for loop iterates once through each row of the matrix, which is already correct; you just need to change the inner for loop so that instead of iterating over every element in the row, it only iterates through the elements on one side of the diagonal.
If you don't care which "side" of the diagonal (upper or lower) you extract the non-zero elements from, it's easiest to get them from the lower side of the diagonal, by doing this:
for row_num in range(len(X)):
for col_num in range(row_num):
if X[row_num][col_num] > 0:
non_zero_entries.append(X[row_num][col_num])
Note that instead of using a "for-each" loop, where the loop variable is each entire row, we use a for loop with a range, where the loop variable is a number. This has equivalent behavior (X[row_num] is the same as i in your original code), but allows us to have a variable that counts which row the loop is currently on. This number, row_num, is equal to the index within the row (the column number) that is the "diagonal" entry. Thus the inner for loop can use a range that ends at row_num, rather than len(X[row_num]), to only iterate over the entries from 0 to the "diagonal" entry.
If you specifically want the entries from the upper side of the diagonal, the inner for loop's range needs to be a little more complicated:
for row_num in range(len(X)):
for col_num in range(row_num+1, len(X[row_num])):
if X[row_num][col_num] > 0:
non_zero_entries.append(X[row_num][col_num])
In this code, range(row_num+1, len(X[row_num])) produces a range for the inner for loop that starts at the entry after the "diagonal" entry, and ends at the end of the row.
I have the written the code below, it's not ready yet but I ran into problems when testing it. The goal is to check whether or not numbers 1 to 9 appear more than once in one single row:
def rivi_oikein(sudoku: list, rivi_nro: int):
unique_list = [] #4
row = sudoku[rivi_nro]
zeros = row.count(0) #6
others = len(unique_list)
for i in row:
if i not in unique_list:
unique_list.append(i)
print(unique_list) # prints -> [9, 0, 8, 3]
print(row) # prints -> [9, 0, 0, 0, 8, 0, 3, 0, 0]
print(others) # prints -> 0
print(zeros) # prints -> 6
if __name__ == "__main__":
sudoku = [
[9, 0, 0, 0, 8, 0, 3, 0, 0],
[2, 0, 0, 2, 5, 0, 7, 0, 0],
[0, 2, 0, 3, 0, 0, 0, 0, 4],
[2, 9, 4, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 7, 3, 0, 5, 6, 0],
[7, 0, 5, 0, 6, 0, 4, 0, 0],
[0, 0, 7, 8, 0, 3, 9, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 3],
[3, 0, 0, 0, 0, 0, 0, 0, 2]
]
print(rivi_oikein(sudoku, 0))
enter code here
What confuses me is the "print(others) as it's supposed to be "len(unique_list)" which contains 4 numbers. Why the len() isn't working?
Sorry for the bad indent. I can't figure out how to copy+paste it correctly.
When you run others = len(unique_list), the length of unique_list really is 0. This syntax doesn't forever bind the variable others to the length of unique_list; it just grabs whatever that length is at the moment of running that instruction, and stores it (as a number, completely independent from unique_list henceforth) within others, so that's what you're seeing.
You could, for instance, print(len(unique_list)) instead if what you want is to find the length of it at the time of printing; or, if you do want to store it as well, assign that value when it makes sense (i.e, when the list is at the state you wish to sample):
others = len(unique_list)
print(others)
or some such thing.
what would be the quickest way to get to :
[[0, 2, 0, 0],\
[0, 2, 0, 0],\
[0, 2, 0, 0],\
[0, 2, 0, 0]]
from:
[[0, 0, 2, 0],\
[0, 0, 2, 0],\
[0, 0, 2, 0],\
[0, 0, 2, 0]]
without using numpy or any other external library
For your specific task:
l = [[0, 2, 0, 0], [0, 2, 0, 0], [0, 2, 0, 0], [0, 2, 0, 0]]
for arr in l:
arr[1], arr[2] = arr[2], arr[1]
Let's say we have a list l, which is [0, 0, 2, 0], and we want to shift all the elements one place to left.
Firstly, we need to get all the elements to the right except the first one. List slicing l[1:] would work here, which would get [0, 2, 0].
Secondly, we need to get the remaining elements on the left with l[1:], which would get [0].
You can now probably see that we can shift the elements one place to the left with adding the above 2 lists together:
>>> lst = [0, 0, 2, 0]
>>> first = lst[1:]
>>> second = lst[:1]
>>> first + second
[0, 2, 0, 0]
Which can be summarized in this function:
def shift(lst, n):
return lst[n:] + lst[:n]
Since this can shift one lists position, it can applied to all lists in a nested list and shift their positions to left by 1:
nested_lst = [shift(sublist, 1) for sublist in nested_lst]
I have two arrays, one array that contains all indices of two arrays that meet a certain condition I had made previous to this. The other array is an array of booleans. I want to take the array of indices and find the same place in the array of booleans and replace those values.
So for example what I am looking to do is:
myIdxs = [0, 3, 5]
myBools = [1, 0, 0, 1, 1, 1, 0, 1, 0, 1]
and change myBools to:
myBools = [0, 0, 0, 0, 1, 0, 0, 1, 0, 1]
I've tried:
myBools = [myBools[i] for i in myIdx == 0]
But this does not give me the desired output.
I hope this works (not sure what you need):
myIdxs = [0, 3, 5]
myBools = [1, 1, 1, 1, 1, 0]
myBools = [myBools[i] if i in myIdxs else 0
for i in xrange(len(myBools))]
>>> print myBools
[1, 0, 0, 1, 0, 0]
Poorly worded question, but here are two answers, both are extremely simple and straightforward, and don't required complex list comprehension.
If you want to change the bit to the opposite value
myIdxs = [0, 3, 5]
myBools = [1, 0, 0, 1, 1, 1, 0, 1, 0, 1]
for i in myIdxs:
myBools[i] ^= 1 # Bitwise operator flips the bit
print(myBools)
If you want to change the bit to zero.
myIdxs = [0, 3, 5]
myBools = [1, 0, 0, 1, 1, 1, 0, 1, 0, 1]
for i in myIdxs:
myBools[i] = 0 # Sets bit to zero
print(myBools)
Output
The output is actually the same for both, given the input, but don't let that fool you they do two very different things.
[0, 0, 0, 0, 1, 0, 0, 1, 0, 1]
[0, 0, 0, 0, 1, 0, 0, 1, 0, 1]
Try using list comprehension with if-else statement.
[myBools[i] if i in myIdxs else 0 for i in range(len(myBools))]
Output
[1, 0, 0, 1, 0, 0]
I have a list of lists and I want to create multiple smaller lists from specific indexes in this list. If I have this big "matrix" can I create a small list made up of integers collected from this matrix?
Code:
matrix = [
[0, 0, 0, 5, 0, 0, 0, 0, 6],
[8, 0, 0, 0, 4, 7, 5, 0, 3],
[0, 5, 0, 0, 0, 3, 0, 0, 0],
[0, 7, 0, 8, 0, 0, 0, 0, 9],
[0, 0, 0, 0, 1, 0, 0, 0, 0],
[9, 0, 0, 0, 0, 4, 0, 2, 0],
[0, 0, 0, 9, 0, 0, 0, 1, 0],
[7, 0, 8, 3, 2, 0, 0, 0, 5],
[3, 0, 0, 0, 0, 8, 0, 0, 0],
]
list1 = ([index 1, row 1], [index 2, row 2])
list2 = ([index 3, row 6], [index 7, row 9])
etc.
How would I do this correctly in Python. Help me fill in what would actually go in the parenthesis.
Thanks!
if index1 means FIRST index, row1 means FIRST row,
then matrix[0][0] = 0 in this case.
matrix[1][0] = 8
matrix[1][5] = 7
In all, you can do matrix[row_index][col_index]
So
list1 = [ matrix[0,0], matrix[2][2] ]
Hope this helps.
list1 = [matrix[1][1], matrix[2][2]]
list2 = [matrix[6][3], matrix[9][7]]
etc...
You basically have a list of lists here. You call items in a list by:
listname[index]
SO....
matrix[0] will give you [0, 0, 0, 5, 0, 0, 0, 0, 6]
matrix[0][0] will give you 0.... that is, the zero-th element of the zero-th list.
Remember, the "first" element of any list is really the zero-th element. So matrix[1] will give you the "second" thing in your list.
list1 = [matrix[1][1], matrix[2][2]]
list2 = [matrix[6][3], matrix[9][7]]
Also a note to help you ask better questions... the examples you gave call for lists but your examples are items grouped by parentheses which denote tuples. Lists are denoted by square brackets. []
something like this:
newmatrix = []
for n,i in enumerate(matrix[0]):# assuming the lists are in the same length
templist =[]
for l in matrix:
templist.append(l[n])
print "templist: ",n,"content: ",templist
newmatrix.append(templist)
edit: just realized that I completly misread the question. not relevant answer, sorry. not deleting because maybe this could be relevant for someone else