python list comprehension double for

list-comprehension, python

Solution

Lets break it down.

A simple list-comprehension:

[x for x in collection]

This is easy to understand if we break it into parts: `[A for B in C]`

- `A` is the item that will be in the resulting list

- `B` is each item in the collection `C`

- `C` is the collection itself.

In this way, one could write:

[x.lower() for x in words]

In order to convert all words in a list to lowercase.

It is when we complicate this with another list like so:

[x for y in collection for x in y] # [A for B in C for D in E]

Here, something special happens. We want our final list to include `A` items, and `A` items are found inside `B` items, so we have to tell the list-comprehension that.

- `A` is the item that will be in the resulting list

- `B` is each item in the collection `C`

- `C` is the collection itself

- `D` is each item in the collection `E` (in this case, also `A`)

- `E` is another collection (in this case, `B`)

This logic is similar to the normal for loop:

for y in collection:     #      for B in C:
    for x in y:          #          for D in E: (in this case: for A in B)
        # receive x      #              # receive A

To expand on this, and give a great example + explanation, imagine that there is a train.

The train engine (the front) is always going to be there (the result of the list-comprehension)

Then, there are any number of train cars, each train car is in the form: `for x in y`

A list comprehension could look like this:

[z for b in a for c in b for d in c ... for z in y]

Which would be like having this regular for-loop:

for b in a:
    for c in b:
        for d in c:
            ...
                for z in y:
                    # have z

In other words, instead of going down a line and indenting, in a list-comprehension you just add the next loop on to the end.

To go back to the train analogy:

`Engine` - `Car` - `Car` - `Car` ... `Tail`

What is the tail? The tail is a special thing in list-comprehensions. You don't need one, but if you have a tail, the tail is a condition, look at this example:

[line for line in file if not line.startswith('#')] 

This would give you every line in a file as long as the line didn't start with a hashtag (`#`), others are just skipped.

The trick to using the "tail" of the train is that it is checked for True/False at the same time as you have your final 'Engine' or 'result' from all the loops, the above example in a regular for-loop would look like this:

for line in file:
    if not line.startswith('#'):
        # have line

please note: Though in my analogy of a train there is only a 'tail' at the end of the train, the condition or 'tail' can be after every 'car' or loop...

for example:

>>> z = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
>>> [x for y in z if sum(y)>10 for x in y if x < 10]
[5, 6, 7, 8, 9]

In regular for-loop:

>>> for y in z:
    if sum(y)>10:
        for x in y:
            if x < 10:
                print x

5
6
7
8
9

Problem

``` vec = [[1,2,3], [4,5,6], [7,8,9]] print [num for elem in vec for num in elem] <----- this >>> [1, 2, 3, 4, 5, 6, 7, 8, 9] ``` This is tricking me out. I understand elem is the lists inside of the list from `for elem in vic` I don't quite understand the usage of `num` and `for num in elem` in the beginning and the end. How does python interpret this? What's the order it looks at?

Original source

Related problems