How to use list comprehensions for this? - python-3.x

I want to take input of 2 numbers: the number of rows and the number of columns. I then want to use these to output a matrix numbered sequentially. I want to do this using a list comprehension. The following is a possible output.
>>>> my_matrix = matrix_fill(3, 4)
>>>> my_matrix
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
I am using the following code to output a sequentially numbered list:
def matrix_fill(num_rows, num_col):
list=[i for i in range(num_col)]
return (list)
I cannot, however, figure out how to make the sequential list of numbers break into the separate lists as shown in the output based on num_rows.

I don't think you need itertools for that. The range function can take a step as a parameter. Like this:
def matrix_fill(rows,cols):
return [[x for x in range(1,rows*cols+1)][i:i+cols] for i in range(0,rows*cols,cols)]
And then it works as expected.
>>> matrix_fill(3,4)
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
Let's break this down a little bit and understand what's happening.
>>> [x for x in range(1,3*4+1)]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
So what we want to do is to get a new slice every four elements.
>>> [x for x in range(1,3*4+1)][0:4]
[1, 2, 3, 4]
>>> [x for x in range(1,3*4+1)][4:8]
[5, 6, 7, 8]
>>> [x for x in range(1,3*4+1)][8:12]
[9, 10, 11, 12]
So we want to iterate over the elements of the list[x for x in range(1,3*4+1)] of length "rows*cols" ( 3 * 4 ), create a new slice every "cols" number of elements, and group these slices under a single list. Therefore, [[x for x in range(1,rows*cols+1)][i:i+cols] for i in range(0,rows*cols,cols)] is a suitable expression.

Nest a list comprehension inside another one, use itertools.count() to generate the sequence:
import itertools
rows = 3
cols = 4
count_gen = itertools.count() # pass start=1 if you need the sequence to start at 1
my_matrix = [[next(count_gen) for c in range(cols)] for r in range(rows)]
print(my_matrix)
# prints: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
# As a function
def matrix_fill(rows, cols):
count_gen = itertools.count()
return [[next(count_gen) for c in range(cols)] for r in range(rows)]

If you used the numpy module, the method is extremely simple, with no list comprehension needed.
my_matrix = np.arange(1, 13).reshape(3,4)
Printing the variable my_matrix shows
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]

Related

How to find missing numbers from list in Python?

lst = [1, 4, 5, 9, 6]
How to write a code to get some missing values which must return [2, 3, 7, 8]?
Here is my code
new_list = []
for i in range(1, len(lst1)):
if i not in lst1:
new_list.append(i)
print(new_list)
You can convert them to sets and use "-" to calculate the difference. Note that the order is important.
You need to define what you want to compare your list to if you want to find the missing elements. You can automatically do this if it is simple like "the numbers from 1 to 10" using the code:
list(range(1, 10))
The comparison code is:
lst1 = [1, 4, 5, 9, 6]
lst2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
out = list(set(lst2) - set(lst1))
print(out)
which returns
[8, 2, 3, 7]
It isn't clear exactly what you want from your question, if you give a more detail it will be easier to help.

Add elements of unknown list length - Python

I seem to be struggling a little with this issue. Let's say you have a list of various lengths i.e:
first_list = [8, 7, 5, 1, 2, 4]
or
second_list = [6, 8, 4, 1]
regardless of how long or short the list is how would you be able to add the elements of each list such that all the elements get added together? I.e First > first + second > first + second + third > ... etc
first_list = [8, 8+7, 8+7+5, 8+7+5+1, 8+7+5+1+2, 8+7+5+1+2+4]
second_list = [6, 6+8, 6+8+4, 6+8+4+1]
I have tried a few different things but just don't seem to be able to do this :-/
Try this:
for i in range(1,len(myList)):
myList[i] += myList[i-1]
You can also use a list comprehension:
>>> my_list = [8, 7, 5, 1, 2, 4]
>>> [sum(my_list[:i+1]) for i in range(len(my_list))]
[8, 15, 20, 21, 23, 27]
Note that even though this looks more compact, #MarkSnyder's answer is actually more performant as it has a time complexity of O(n) while this one is O(n^2).
Edit: If you are using Python 3.8 or higher, you can use the walrus operator to have a list comprehension with O(n) complexity:
>>> my_list = [8, 7, 5, 1, 2, 4]
>>> s = 0
>>> [s := s + i for i in my_list]
[8, 15, 20, 21, 23, 27]

List and Dictionary Output mismatch for the same Input in Python 3

I have the following function which makes use of a dictionary of cycle_times to generate lists and dictionaries containing elements whose values are greater than a certain threshold.
def anamolous_cycle_time_index_and_lengths(cycle_time_dict, anamoly_threshold):
for meter,cycle_time_list in cycle_time_dict.items():
anamoly_dict = {cycle_time_list.index(x):x for x in cycle_time_list if x > anamoly_threshold}
anamoly_list = [x for x in cycle_time_list if x > anamoly_threshold]
print(meter,len(anamoly_dict))
print([value for key,value in anamoly_dict.items()])
print(anamoly_list)
Suppose I give the inputs as
new_dict = {104:[2,3,4,5,6,7,3,2,5,6,7], 101:[2,45,4,2,5,2,34,2,5,6,7], 106:[2,23,4,5,65,7,3,23,5,6,7]}
anamoly_threshold = 3
The outputs I get are
104 4
[4, 5, 6, 7]
[4, 5, 6, 7, 5, 6, 7]
101 6
[45, 4, 5, 34, 6, 7]
[45, 4, 5, 34, 5, 6, 7]
106 6
[23, 4, 5, 65, 7, 6]
[23, 4, 5, 65, 7, 23, 5, 6, 7]
Shouldn't the list and dictionary give me the same output? I have run a comprehension for both data structures on the same data.
Your problem is the use of .index(x). This returns the index for the first occurrence of x. And since dictionary keys are unique, you will see only the first occurrence of duplicate elements in your dict comprehension.
There are several ways to overcome this problem. The easiest is to use enumerate:
anamoly_dict = {index: x for index, x in enumerate(cycle_time_list) if x > anamoly_threshold}
Now the output for both methods is the same.

Python: Bug in writing a transpose function using lists

I have an assignment to do, which is:
Write a function transpose which takes in a matrix and transposes it. Basically, this converts a m x n matrix into a n x m matrix.
I wrote a code which seems sensible, but it doesnt get me the result I want. Can anyone point out what is wrong with my code?
def transpose(matrix):
new_matrix=[[]]*len(matrix[0])
for row in matrix:
i=0
for j in row:
new_matrix[i]+=[j]
i+=1
return new_matrix
Test case:
print(transpose([[ 1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]))
If you use the * to multiply some values in a list-initialisation, be careful. You might end up with references that point multiple times to the same value:
l = [ [] ]*3
print(l)
l[1].append(34) # change only "the first" list by appending smth
print(l)
Output:
[[], [], []]
[[34], [34], [34]] # they are all "the same data" reference
There is an built-in zip() that does exactly your transposing:
l = [[ 1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
l_t = [ list(x) for x in zip(*l)] # one-line solutions for transposing ;)
print(l)
print(l_t) # transposed
Zip has the limitation that it only works to the length of the smallest sublists - yours are all equal so all is fine.
Output:
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
If you ever need a zip that takes the longest list, itertools.zip_longest(..) can be used, it takes a default param that is substituted for any shorter list-items that are not there.
Btw. just list(zip(l)) looks like this: [(1,5,9),(2,6,10),(3,7,11),(4,8,12)] - it create tuples over the same indexes of the parts of the iterable you put into it.
By hand:
l = [[ 1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
l2 = []
for colIdx in range(len(l[0])): # 0-3 iterate over the inner indexes first
newRow = []
for rowIdx in range(len(l)): # 0-2 then over the outer ones
newRow.append(l[rowIdx][colIdx])
l2.append(newRow)
print(l2) # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
What i meant was something like this:
def t(array): #The original array has size mxn
duplicate = [[0 for x in range(len(array))] for y in range(len(array[1]))] #You create an array of size nxm, which is filled with zeros
for i in range(len(array)): #Loop over the rows
for j in range(len(array[i])): #Then loop over the columns
duplicate[j][i] = array[i][j] #Replace j,i or duplicate with i,j th element of original
return duplicate
Now,
>>> t([[ 1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

multiplying elements in a 3x4 matrix individually in python 3 using loops (no numpy)

Im trying to make a matrix that is 3 rows by 4 columns and includes the numbers 1-12. Would then like to multiply those numbers by a factor to make a new matrix.
def matrix(x):
matrix=[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
new_matrix=[[x*1,x*2,x*3],[x*4,x*5,x*6],[x*7,x*8,x*9],[x*10,x*11,x*12]]
print(new_matrix)
This approach works, however it does not use loops, I'm looking for an approach that uses loops, something like this:
def matrix(x):
for i in range(3):
matrix.append([])
for j in range(4):
matrix[i].append(0)
return matrix
You do not need to use explicit loops for something like this (unless you really want to). List comprehensions are a much more efficient way to generate lists, and have a similar syntax to a for loop:
Here is a comprehension for generating any MxN matrix containing the numbers up to M * N:
def matrix(m, n):
return [[x+1 for x in range(row * n, (row + 1) * n)] for row in range(m)]
Here is a comprehension for multiplying the nested list returned by matrix by some factor:
def mult(mat, fact):
return [[x * fact for x in row] for row in mat]
Here is the result for your specific 3x4 case:
>>> m = matrix(3, 4)
>>> print(m)
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
>>> m2 = mult(m, 2)
>>> print(m2)
[[2, 4, 6, 8], [10, 12, 14, 16], [18, 20, 22, 24]]
If you want the indices to be swapped as in your original example, just swap the inputs m and n:
>>> matrix(4, 3)
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
mult will work the same for any nested list you pass in.

Resources