List double for python

python list comprehension double for

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?

That is not that great a dupe target, @Inbar, because it fails to explain anything about how Python interprets the order of the nested loops.

4 Answers 4

A simple list-comprehension:

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:

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.

>>> 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] 
>>> for y in z: if sum(y)>10: for x in y: if x < 10: print x 5 6 7 8 9 

Источник

Читайте также:  Меняем фон сайта с помощью HTML - Нубекс

Double Iteration in List Comprehension [duplicate]

for some suitable sequences a and b. I'm aware of the nested loop semantics of Python's list comprehensions. My question is: Can one iterator in the comprehension refer to the other? In other words: Could I have something like this:

where the current value of the outer loop is the iterator of the inner? As an example, if I have a nested list:

11 Answers 11

Suppose you have a text full of sentences and you want an array of words.

# Without list comprehension list_of_words = [] for sentence in text: for word in sentence: list_of_words.append(word) return list_of_words 

I like to think of list comprehension as stretching code horizontally.

# List Comprehension [word for sentence in text for word in sentence] 
>>> text = (("Hi", "Steve!"), ("What's", "up?")) >>> [word for sentence in text for word in sentence] ['Hi', 'Steve!', "What's", 'up?'] 

This also works for generators

>>> text = (("Hi", "Steve!"), ("What's", "up?")) >>> gen = (word for sentence in text for word in sentence) >>> for word in gen: print(word) Hi Steve! What's up? 

I was wondering, can you do the same with three abstraction levels in a list comprehension? Like chapters in text, sentences in chapters and words in sentences?

I was just suggesting a syntax to loop over the two comprehensions without this backward logic. Not related to solving the original question.

To answer your question with your own suggestion:

>>> [x for b in a for x in b] # Works fine 

While you asked for list comprehension answers, let me also point out the excellent itertools.chain():

>>> from itertools import chain >>> list(chain.from_iterable(a)) >>> list(chain(*a)) # If you're using python < 2.6 
[x for b in a for x in b] This has always bugged be about python. This syntax is so backwards. The general form of x for x in y always has the variable directly after the for, feeds to the expression to the left of the for. As soon as you do a double comprehension, your most recently iterated variable is suddenly so "far". It's awkward, and doesn't read naturally at all

It's even worse: it mixes forwards and backwards. It's as ridiculous as writing 07/04/1776 to refer to the fourth day of the seventh month of the year 1776.

Gee, I guess I found the anwser: I was not taking care enough about which loop is inner and which is outer. The list comprehension should be like:

to get the desired result, and yes, one current value can be the iterator for the next loop.

Ew. I'm not sure this is the "usual" use for list comprehensions, but it's very unfortunate that chaining is so nasty in Python.

Order of iterators may seem counter-intuitive.

Take for example: [str(x) for i in range(3) for x in foo(i)]

def foo(i): return i, i + 0.5 [str(x) for i in range(3) for x in foo(i) ] # is same as for i in range(3): for x in foo(i): yield str(x) 

My understanding is that the reason for this is that "the first iteration listed is the topmost iteration that would be typed if the comprehension were written as nested for loops". The reason this is counterintuitive is that the OUTER loop (topmost if written as nested for-loops) appears at the INSIDE of the bracketed list/dict (comprehension'ed object). Conversely, the INNER loop (innermost when written as nested for-loops) is precisely the rightmost loop in a comprehension, and is in that way appears at the OUTSIDE of the comprehension.

Читайте также:  Python dataframe rename one column

Abstractly written we have [(output in loop 2) (loop 1) (loop 2)] with (loop 1) = for i in range(3) and (loop 2) = for x in foo(i): and (output in loop 2) = str(x) .

This memory technic helps me a lot:

And now you can think about Return + Outer-loop as the only Right Order

Knowing above, the order in list comprehensive even for 3 loops seem easy:

c=[111, 222, 333] b=[11, 22, 33] a=[1, 2, 3] print( [ (i, j, k) # for i in a for j in b for k in c # in order: loop1, loop2, loop3 if i < 2 and j < 20 and k < 200 # ] ) [(1, 11, 111)] 

because the above is just a:

for i in a: # outer loop1 GOES SECOND for j in b: # inner loop2 GOES THIRD for k in c: # inner loop3 GOES FOURTH if i < 2 and j < 20 and k < 200: print((i, j, k)) # returned value GOES FIRST 

for iterating one nested list/structure, technic is the same: for a from the question:

a = [[1,2],[3,4]] [i2 for i1 in a for i2 in i1] which return [1, 2, 3, 4] 

for one another nested level

a = [[[1, 2], [3, 4]], [[5, 6], [7, 8, 9]], [[10]]] [i3 for i1 in a for i2 in i1 for i3 in i2] which return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

Thanks, but what you describe is actually the simple case where the involved iterators are independent. In fact, in your example you could use the iterators in any order and would get the same result list (modulo ordering). The case I was more interested in was with nested lists where one iterator becomes the iterable of the next.

@ThomasH: the order of loop defined in bold is exactly for your need. On the bottom added an example to cover your data and one more example with extra nested level.

ThomasH has already added a good answer, but I want to show what happens:

>>> a = [[1, 2], [3, 4]] >>> [x for x in b for b in a] Traceback (most recent call last): File "", line 1, in NameError: name 'b' is not defined >>> [x for b in a for x in b] [1, 2, 3, 4] >>> [x for x in b for b in a] [3, 3, 4, 4] 

I guess Python parses the list comprehension from left to right. This means, the first for loop that occurs will be executed first.

The second "problem" of this is that b gets "leaked" out of the list comprehension. After the first successful list comprehension b == [3, 4] .

Interesting point. I was surprised at this: x = 'hello'; [x for x in xrange(1,5)]; print x # x is now 4

Читайте также:  Php read csv file to array

Why does it raise "name 'b' is not defined" eventhough it's a local variable ? In that case, why doesn't it raise "name 'x' is not defined" in the first place ?

I could never write double list comprehension on my first attempt. Reading into PEP202, it turns out the reason is that it was implemented in the opposite way you would read it in English. The good news is that it is a logically sound implementation, so once you understand the structure, it's very easy to get right.

Let a, b, c, d be successively nested objects. For me, the intuitive way to extend list comprehension would mimic English:

# works [f(b) for b in a] # does not work [f(c) for c in b for b in a] [f(c) for c in g(b) for b in a] [f(d) for d in c for c in b for b in a] 

In other words, you'd be reading from the bottom up, i.e.

# wrong logic (((d for d in c) for c in b) for b in a) 

However this is not how Python implements nested lists. Instead, the implementation treats the first chunk as completely separate, and then chains the for s and in s in a single block from the top down (instead of bottom up), i.e.

# right logic d: (for b in a, for c in b, for d in c) 

Note that the deepest nested level ( for d in c ) is farthest from the final object in the list ( d ). The reason for this comes from Guido himself:

The form [. for x. for y. ] nests, with the last index varying fastest, just like nested for loops.

Using Skam's text example, this becomes even more clear:

# word: for sentence in text, for word in sentence [word for sentence in text for word in sentence] # letter: for sentence in text, for word in sentence, for letter in word [letter for sentence in text for word in sentence for letter in word] # letter: # for sentence in text if len(sentence) > 2, # for word in sentence[0], # for letter in word if letter.isvowel() [letter for sentence in text if len(sentence) > 2 for word in sentence[0] for letter in word if letter.isvowel()] 

Источник

Python List comprehension double for loop | Example code

Simply do the Outermost loop comes first, and then the inner loops subsequently to get List comprehension double for loop in Python.

The list comprehension should be like this:

Example List comprehension double for loop in Python

list1 = [(x, y) for x in range(0, 3) for y in range(0, 1)] print(list1) 

Python List comprehension double for loop

Another example

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

Output: [5, 6, 7, 8, 9]

How to do a double iteration with list comprehension in Python?

Answer: Use a list comprehension to do a double iteration.

text = [["Hello", "World!"], ["Whats", "Up!"]] res = [word for words in text for word in words] print(res)

Output: [‘Hello’, ‘World!’, ‘Whats’, ‘Up!’]

Do comment if you have any doubts or suggestions on this Python List loop topic.

Note: IDE: PyCharm 2021.3.3 (Community Edition)

Windows 10

Python 3.10.1

All Python Examples are in Python 3, so Maybe its different from python 2 or upgraded versions.

Источник

Оцените статью