Python: Complex for-loops - python

I am working through some code trying to understand some Python mechanics, which I just do not get. I guess it is pretty simple and I also now, what it does, but i do not know how it works. I understand the normal use of for-loops but this here... I do not know.
Remark: I know some Python, but I am not an expert.
np.array([[[S[i,j]] for i in range(order+1)] for j in range(order+1)])
The second piece of code, I have problems with is this one:
for i in range(len(u)):
for j in range(len(v)):
tmp+=[rm[i,j][k]*someFuction(name,u[i],v[j])[k] for k in range(len(rm[i,j])) if rm[i,j][k]]
How does the innermost for-loop work? And also what does the if do here?
Thank you for your help.
EDIT: Sorry that the code is so unreadable, I just try to understand it myself. S, rm are numpy matrices, someFunction returns an array with scalar entries, andtmp is just a help variable

There are quite a few different concepts inside your code. Let's start with the most basic ones. Python lists and numpy arrays have different methodologies for indexation. Also you can build a numpy array by providing it a list:
S_list = [[1,2,3], [4,5,6], [7,8,9]]
S_array = np.array(S_list)
print(S_list)
print(S_array)
print(S_list[0][2]) # indexing element 2 from list 0
print(S_array[0,2]) # indexing element at position 0,2 of 2-dimensional array
This results in:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1 2 3]
[4 5 6]
[7 8 9]]
3
3
So for your first line of code:
np.array([[[S[i,j]] for i in range(order+1)] for j in range(order+1)])
You are building a numpy array by providing it a list. This list is being built with the concept of list comprehension. So the code inside the np.array(...) method:
[[[S[i,j]] for i in range(order+1)] for j in range(order+1)]
... is equivalent to:
order = 2
full_list = []
for j in range(order+1):
local_list = []
for i in range(order+1):
local_list.append(S_array[i, j])
full_list.append(local_list)
print(full_list)
This results in:
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
As for your second snippet its important to notice that although typically numpy arrays have very specific and constant (for all the array) cell types you can actually give the data type object to a numpy array. So creating a 2-dimensional array of lists is possible. It is also possible to create a 3-dimensional array. Both are compatible with the indexation rm[i,j][k]. You can check this in the following example:
rm = np.array(["A", 3, [1,2,3]], dtype="object")
print(rm, rm[2][0]) # Acessing element 0 of list at position 2 of the array
rm2 = np.zeros((3, 3, 3))
print(rm2[0, 1][2]) # This is also valid
The following code:
[rm[i,j][k]*someFuction(name,u[i],v[j])[k] for k in range(len(rm[i,j])) if rm[i,j][k]]
... could be written as such:
some_list = []
for k in range(len(rm[i,j])):
if rm[i, j][k]: # Expecting a boolean value (or comparable)
a_list = rm[i,j][k]*someFuction(name,u[i],v[j])
some_list.append(a_list[k])
The final detail is the tmp+=some_list. When you sum two list they'll be concatenated as can been seen in this simple example:
tmp = []
tmp += [1, 2, 3]
print(tmp)
tmp += [4, 5, 6]
print(tmp)
Which results in this:
[1, 2, 3]
[1, 2, 3, 4, 5, 6]
Also notice that multiplying a list by a number will effectively be the same as summing the list several times. So 2*[1,2] will result in [1,2,1,2].

Its a list comprehension, albeit a pretty unreadable one. That was someome doing something very 'pythonic' in spite of readablity. Just look up list comprehensions and try to rewrite it yourself as a traditional for loop. list comprehensions are very useful, not sure I would have gone that route here.
The syntax for a list comprehension is
[var for var in iterable if optional condition]
So this bottom line can be rewritten like so:
for k in range(len(rm[i,j]):
if rm[i,j][k]:
tmp+= rm[i,j][k]*someFunction(name,u[i],v[j])[k]

Related

Need help understanding this range function

I'm a new programmer and I don't understand:
np.array([range(i, i+3) for i in [2,4,6]])
I know that in the range function there is a start, stop and step, but it's written quite differently here.
The output is a 3*3 array
234
456
678
I don't understand how this array came about. What does the I+3 mean? Are the 2,4,6 x values? What exactly if the for loop doing in this case? What is it iterating over?
Thanks for the help.
If I break down that line of code a little bit I can show you what happens.
The following line is a list comprehension, it's saying return I where I is set to each number in the list [2,4,6]. This returns a list that looks like [2,4,6]. So that's essentially useless because you're not manipulating your original list.
[I for I in [2,4,6]]
when you put this inside np.array() it just creates an array from your list.
Now with the following code, your going through each number in the range 2-5 not including 5 (5 is I+3)
for i in range(2,5):
print(i)
2
3
4
You could also do
for i in range(2,5):
print(np.array([range(2,4)]))
[[2 3]]
[[2 3]]
[[2 3]]
Which is a loop that executes 3 times, and prints an array which contains a range from 2-4 in it.
When you combine everything in
[range(I, I+3) for I in [2,4,6]]
You're saying for each number in the list [2,4,6] return a range from that number up to that number + 3 and put that in a list, which returns
[range(2, 5), range(4, 7), range(6, 9)]
Then you convert that to an array to get
array([[2, 3, 4],
[4, 5, 6],
[6, 7, 8]])
np.array( # This is a numpy library's 2D data structure array.
[
range(i, i+3) # range function which produces iterator from i to i+2 (exclusive of end) i.e. if i = 1, range(1, 4) will give [1, 2, 3]
for i in [2,4,6] # Basic list comprehension for loop
]
)

Iterate Python List of Lists and Remove Final Index of Each Sublist, No Imports

There are a few similar questions to this one but not exactly the same:
I want to dynamically decrease a given input array or list of lists. For example:
matrix = [[0,1,2], [3,4,5],[6,7,8]]
Starting at 0 I need to iterate through and remove the final index - the iterative. So the output I would like to store in a new list is:
#output
[0,1,2], ,[3,4], [6]]
[0,1,2], ,[3,4], [6]] ==> which then flattens to [0,1,2,3,4,6]
Here's what I'm currently going after:
def get_list(matrix, stop_index):
temp = []
for i in range(0, stop_index):
for m in matrix:
temp.append(matrix[0:stop_index])
outside_list.append(temp)
return outside_list
I believe I am seeing well my over reliance on packages and libraries, so I am really trying to do this without outside packages or imports
Thank you for any help! I don't forget to green check mark.
Using list comprehension
l = [[0,1,2], [3,4,5],[6,7,8]]
ll = [ x[:len(l)-l.index(x)] for x in l]
# [[0, 1, 2], [3, 4], [6]]
print([x for y in ll for x in y ])
# [0, 1, 2, 3, 4, 6]
Simpler syntax:
matrix = [[0,1,2], [3,4,5],[6,7,8]]
outside_list = list()
for i in range(len(matrix)):
# matrix[i] is used to access very sublist in the matrix,
#[:3-i] is to slice every sublist from the beginning to (3 - current position)
outside_list.append(matrix[i][:3-i])
print(outside_list)
Some useful refernces
List slicing https://stackoverflow.com/a/509295/8692977
List comprehension: https://stackoverflow.com/a/34835952/8692977

need to grab entire first element (array) in a multi-dimentional list of arrays python3

Apologies if this has already been asked, but I searched quite a bit and couldn't find quite the right solution. I'm new to python, but I'll try to be as clear as possible. In short, I have a list of arrays in the following format resulting from a joining a multiprocessing pool:
array = [[[1,2,3], 5, 47, 2515],..... [[4,5,6], 3, 35, 2096]]]
and I want to get all values from the first array element to form a new array in the following form:
print(new_array)
[1,2,3,4,5,6]
In my code, I was trying to get the first value through this function:
new_array = array[0][0]
but this only returns the first value as such:
print(new_array)
[1,2,3]
I also tried np.take after converting the array into a np array:
array = np.array(array)
new_array = np.take(results,0)
print(new_array)
[1,2,3]
I have tried a number of np functions (concatenate, take, etc.) to try and iterate this over the list, but get back the following error (presumably because the size of the array changes):
ValueError: autodetected range of [[], [1445.0, 1445.0, -248.0, 638.0, -108.0, 649.0]] is not finite
Thanks for any help!
You can achieve it without numpy using reduce:
from functools import reduce
l = [[[1,2,3], 5, 47, 2515], [[4,5,6], 3, 35, 2096]]
res = reduce(lambda a, b: [*a, *b], [x[0] for x in l])
Output
[1, 2, 3, 4, 5, 6]
Maybe it is worth mentioning that [*a, *b] is a way to concatenate lists in python, for example:
[*[1, 2, 3], *[4, 5, 6]] # [1, 2, 3, 4, 5, 6]
You could also use itertools' chain() function to flatten an extraction of the first subArray in each element of the list:
from itertools import chain
result = list(chain(*[sub[0] for sub in array]))

How to properly remove elements from array in loop using Python

I tried to remove only one element from an array and print remaining ones in a loop:
arr = [1,2,3,4,5]
for i in arr:
a = arr
a.remove(i)
print a
So I am expecting it to print this:
[2, 3, 4, 5]
[1, 3, 4, 5]
[1, 2, 3, 5]
[1, 2, 3, 4]
Why am I gettting the following results instead:
[2, 3, 4, 5]
[2, 4, 5]
[2, 4]
This is a classic problem of deep vs shallow copy.
Python copies the array by reference. So, any changes to the new variable (a in your case) will be reflected in the main array (arr). Removing element from a also remove elements from arr.
You need to use following for creating a copy.
a = arr[:]
This will not remove any elements from arr.
You've already got explanations, I'll provide an alternative - you can produce requested output without using remove at all:
arr = [1,2,3,4,5]
for i in arr:
a = [x for x in arr if x != i]
print a
(beware of non-unique elements in arr, if there are any, both this code and yours will produce unexpected results, though in different ways).
You can try this.
arr = [1, 2, 3, 4, 5, 6, 7 ]
for index, item in enumerate(arr):
print(arr[0:index] + arr[index+1:])
I think this can help you.
If you don't have any repeated value you can use this too.
for item in arr:
print(set(arr) - set([item]))
Python lists are mutable i.e. modifying operations (like list.remove()) on them do not produce a new list but modify the existing list instead so each your cycle actually permanently modifies the source list and elements are lost. You'd need to copy your whole list each time you want to modify it in order to achieve what you want, or you can create a new list with elements excluded, or, for very long lists, reconstructing by slicing is probably the most performant way:
arr = [1,2,3,4,5]
for i in range(len(arr)):
a = arr[0:i] + arr[i+1:]
print(a)

Matrix in python

I am very new to Python, I need to read numbers from a file and store them in a matrix like I would do it in fortran or C;
for i
for j
data[i][j][0]=read(0)
data[i][j][1]=read(1)
data[i][j][2]=read(2)
...
...
How can I do the same in Python? I read a bit but got confused with tuples and similar things
If you could point me to a similar example it would be great
thanks
Python doesn't come with multi-dimensional arrays, though you can add them through the popular numpy third-party package. If you want to avoid third-party packages, what you would do in Python would be to use a list of lists of lists (each "list" being a 1-D "vector-like" sequence, which can hold items of any type).
For example:
data = [ [ [0 for i in range(4)] for j in range(5)] for k in range(6)]
this makes a list of 6 items which are lists of 5 items which are lists of 4 0's -- i.e., a 6 x 5 x 4 "3D matrix" which you could then address the way you want,
for i in range(6):
for j in range(5):
data[i][j][0]=read(0)
data[i][j][1]=read(1)
data[i][j][2]=read(2)
to initialize the first three of the four items on each most-nested sublist with calls to that mysterious function read which presumably you want to write yourself (I have no idea what it's supposed to do -- not "read and return the next number" since it takes a mysterious argument, but, then what?).
It depends on your file format, but take a look on:
Link
and
http://docs.scipy.org/doc/scipy/reference/tutorial/io.html
You may want to use numpy and use the built in function for using I/O, in particular loadtxt.
http://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html
There are a lot of addictional functions to handle I/O:
http://docs.scipy.org/doc/numpy/reference/routines.io.html
A simple example would be:
data = []
with open(_filename_, 'r') as f:
for line in f:
data.append([int(x) for x in line.split()])
A way to extend the list in a form to work like matrix. I have gone through other codes of matrix in python, all are using comprehensions to first initialize a list of required size and then update the values (which takes a little more time).Let the r represents row and c for column.
r = input('Enter row size: ')
c = input('Enter column size: ')
m = []
for i in range(r):
m.append([])
for j in range(c):
m[i].append(input())
for i in m:
print i
Here, you can input the elements of matrix as it was in 'C' or equivalent languages. Hope this may help someone a different view of implementing matrices.
Matrices are two dimensional structures. In plain Python, the most natural representation of a matrix is as a list of lists.
So, you can write a row matrix as:
[[1, 2, 3, 4]]
And write a column matrix as:
[[1],
[2],
[3],
[4]]
This extends nicely to m x n matrices as well:
[[10, 20],
[30, 40],
[50, 60]]
See matfunc.py for an example of how to develop a full matrix package in pure Python.
The documentation for it is here.
And here is a worked-out example of doing matrix multiplication in plain python using a list-of-lists representation:
>>> from pprint import pprint
>>> def mmul(A, B):
nr_a, nc_a = len(A), len(A[0])
nr_b, nc_b = len(B), len(B[0])
if nc_a != nr_b:
raise ValueError('Mismatched rows and columns')
return [[sum(A[i][k] * B[k][j] for k in range(nc_a))
for j in range(nc_b)] for i in range(nr_a)]
>>> A = [[1, 2, 3, 4]]
>>> B = [[1],
[2],
[3],
[4]]
>>> pprint(mmul(A, B))
[[30]]
>>> pprint(mmul(B, A), width=20)
[[1, 2, 3, 4],
[2, 4, 6, 8],
[3, 6, 9, 12],
[4, 8, 12, 16]]
As another respondent mentioned, if you get serious about doing matrix work, it would behoove you to install numpy which has direct support for many matrix operations:

Categories