Comprehension on a nested iterables?
Here is how you would do this with a nested list comprehension:
[[float(y) for y in x] for x in l]
This would give you a list of lists, similar to what you started with except with floats instead of strings. If you want one flat list then you would use [float(y) for x in l for y in x]
.
Explanation of how nested list comprehension works?
Ah, the incomprehensible "nested" comprehensions. Loops unroll in the same order as in the comprehension.
[leaf for branch in tree for leaf in branch]
It helps to think of it like this.
for branch in tree:
for leaf in branch:
yield leaf
The PEP202 asserts this syntax with "the last index varying fastest" is "the Right One", notably without an explanation of why.
Understanding nested list comprehension
The short answer is: yes, you are correct in your understanding.
There's only a catch: the way you normally use nested list comprehension in python code is to operate on multidimensional arrays.
A typical example is when you operate on matrices:
>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [[el - 1 for el in row] for row in matrix]
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]
As you can see the "nesting" works by operating on each dimension of the matrix.
In the examples you provided, it seems that ySet
[unfortunate name btw, as sets are one of the types provided with python] is just a generic counter, which makes a bit harder to follow what is going on under the hood.
As for your first example:
>>> rows = ([1, 2, 3], [10, 20, 30])
>>> [(min([row[i] for row in rows]),max([row[i] for row in rows])) for i in range(len(rows[0]))]
[(1, 10), (2, 20), (3, 30)]
You might wish to look into the zip built-in function:
>>> zip(rows[0], rows[1])
[(1, 10), (2, 20), (3, 30)]
or for maximum brevity and elegance:
>>> zip(*rows)
[(1, 10), (2, 20), (3, 30)]
HTH!
How to make a nested list comprehension?
result = [item for row in prices for item in row]
print(result)
What is the under the hood reason that we can use nested for loops in list comprehensions
Your first translation should be
li=[]
for item in iterable:
li.append( expression )
Your example [s+z for s in iterable_1 for z in iterable_2]
is translated as
li=[]
for s in iterable_1:
for z in iterable_2:
li.append(s+z)
Congrats, you have discovered ... monads! which are essentially what you've described, generalized nested loops.
Nested loops just produce a plain stream of results. Nested lists, when flattened, also turn into a plain stream of elements. That's the similarity. A lazy append
is pretty much like yield
.
Each monad type is defined by how it implements its version of the flatMap
function, which is a map followed by the flattening of the resulting nested structure. The flattening of the nested structure at each nesting level allows for an arbitrary depth of nesting to be flattened:
M [M (a)] ==> M (a)
M [M [M (a)]] ==> # flatten the two outer layers first:
M [M (a)] ==> M (a)
OR:
==> # flatten the two inner layers first:
M [M (a)] ==> M (a)
See the difference? There isn't any! Any type that does the above, is a "monad". Like lists.
So it is with loops as well, which can be nested to an arbitrary depth -- two, three, whatever, it doesn't matter. The whole structure is still producing its results one by one, and these are the results which the innermost loop is producing, one by one.
That is the under the hood reason why we can use nested for
loops in list comprehensions. Or, saying the same thing in a fancy way, it is because list comprehensions are just like monadic chains of operations (and can be translated as such).
Nested list comprehension understanding for comparing strings in python
When you write:
l3 = [x for x in l1 for y in l2 if y in x]
It's equal to the following:
l3 = []
for x in l1: # loop through each element in the list l1
for y in l2: # loop through each element in the list l2
if y in x: # if x contains y
l3.append(x)
Nested list comprehension not the same as nested for loop
Your list comprehension doesn't do anything as it does not run without i
already been defined outside the list comprehension.
To achieve what you want (and yes, this is counter intuitive ) you need to do this:
[j for i in range(1,5) for j in range(0,i)]
This will yield:
[0, 0, 1, 0, 1, 2, 0, 1, 2, 3]
which is the same order as your nested for loops.
Nested list comprehension on python
This should do it:
value = ['a','b','c','d','e','f']
key = [2, 3, 1, 1, 3, 2]
answer = {}
for k, v in zip(key, value):
if k in answer:
answer[k].append(v)
else:
answer[k] = [v]
print(answer)
{2: ['a', 'f'], 3: ['b', 'e'], 1: ['c', 'd']}
EDIT: oops, jumped the gun. Apologies.
Here's the comprehension version, but it's not very efficient:
{
k: [v for i, v in enumerate(value) if key[i] == k]
for k in set(key)
}
EDIT 2:
Here's an one that has better complexity:
import pandas as pd
series = pd.Series(key)
{
k: [value[i] for i in indices]
for k, indices in series.groupby(series).groups.items()
}
Related Topics
Scope of Lambda Functions and Their Parameters
How to Have Clusters of Stacked Bars
X, = ... - Is This Trailing Comma the Comma Operator
Using Python Requests with JavaScript Pages
Intuition and Idea Behind Reshaping 4D Array to 2D Array in Numpy
What Are the Arguments to Tkinter Variable Trace Method Callbacks
How to Initialize a Two-Dimensional Array in Python
Pandas: Filter Rows of Dataframe with Operator Chaining
Numpy Array Is Not JSON Serializable
Finding Local Maxima/Minima with Numpy in a 1D Numpy Array
Plot Logarithmic Axes with Matplotlib in Python
Replace Non-Ascii Characters with a Single Space
Method Resolution Order (Mro) in New-Style Classes
How to Filter a Dictionary According to an Arbitrary Condition Function
How to Read a Text File into a List or an Array with Python