Zygimantas
Zygimantas

Reputation: 8827

Combining multiple for loops in Python

Let's say, we have and list of objects in variable called "articles", each object has a member "tags" (which is simple list).

Expected output: all tags in all articles, joined in a single list.

In multiple lines, solution would be:

arr = []
for article in articles:
    for tag in article.tags:
       arr.append(tag)

Now, how can we write this in single line instead of 4?

This syntax is invalid:

arr = [tag for tag in article.tags for article in articles]

Thanks!

Upvotes: 4

Views: 5626

Answers (6)

Hugh Bothwell
Hugh Bothwell

Reputation: 56714

If you want unique tags, you might be better served by

import operator
tags = reduce(operator.__or__, (set(article.tags) for article in articles), set())

Edit:

  • For Python 3, you would need to

    from functools import reduce
    
  • The initializer set() is returned if the sequence is empty, rather than throwing an error.

Upvotes: 2

marr75
marr75

Reputation: 5725

This is already answered multiple times, but it can be helpful to break lines and indent:

arr = [tag 
       for article in articles
           for tag in article.tags]

This has the advantage of

  1. Making it more readable if you needed to do some kind of projection on tag (like getting (tag.name, tag.description, tag.count) or some other tuple or transformation of a tag)
  2. Making the syntax for nested generator expressions more readable to a beginner
  3. Making complex nested generator expressions more readable

Upvotes: 2

Tomas Aschan
Tomas Aschan

Reputation: 60674

Perhaps

arr = [tag for tag in (a.tags for a in articles)]

Upvotes: 4

Jess
Jess

Reputation: 6987

Try this:

import itertools
it = itertools.chain.from_iterable(article.tags for article in articles)
l  = list(it) # if you really need a list and not an iterator

Upvotes: 2

Mike Lewis
Mike Lewis

Reputation: 64177

You are actually looping in the order that you don't want to order:

what you want is:

result = [ tag for article in articles for tag in article.tags ]

To translate what you were doing in your example would be:

for tag in article.tags:
    for article in articles:
       #code

which doesn't make much sense.

Upvotes: 5

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 799520

It's invalid because article doesn't exist by the time the first loop is parsed.

arr = [tag for article in articles for tag in article.tags]

Upvotes: 11

Related Questions