2

So I'm currently working with mongoengine, although anything with properties will have the same behavior.

I have a list called collections. Technically it's a mongoengine QuerySet, which is an iterable, but it has virtually all the same behaviors as a list.

Each element collections is an object, with a property called addons which is also a list.

I want to create a flat list of all the addons. Currently doing this produces the desired result

addons = []
for col in collections:
    addons+=col.addons

But when I try this, which I assume is the equivalent list comprehension, I get a list of lists (it essentially appends each list together instead of adding them)

addons = [col.addons for col in collections]

I've been reading about nested list comprehensions and even using itertools but haven't been able to figure out how to get either to work properly

Jared Joke
  • 1,226
  • 2
  • 18
  • 29
  • It's not the same. That's a list of lists. This is a list of objects that have a list as one of their properties, meaning I can't simply do a nesting of for loops – Jared Joke Dec 04 '13 at 19:14
  • Sure you could: `[item for col in collections for item in col.addons]` – David Robinson Dec 04 '13 at 21:27

2 Answers2

2

You can use itertools.chain.from_iterable like so:

from itertools import chain
addons = list(chain.from_iterable(col.addons for col in collections))

Available on Python >= 2.6. In the past, it's been quite fast. Faster even than the double list comprehension.

GrantJ
  • 8,162
  • 3
  • 52
  • 46
  • Awesome! That did the trick and was, indeed, super fast. Thanks! – Jared Joke Dec 04 '13 at 19:25
  • @JaredJoke you can map it either way. The itertools module provides an imap function so you could do list(chain.from_iterable(imap(processing_func, col.addons) for col in collections))) – GrantJ Dec 04 '13 at 19:32
1

you need a double list comprehension, like:

addons = [item for item in col.addons for col in collections]
Cameron Sparr
  • 3,925
  • 2
  • 22
  • 31
  • I tried that and got an error. UnboundLocalError: local variable 'col' referenced before assignment – Jared Joke Dec 04 '13 at 19:22
  • 2
    Should probably be `[item for col in collections for item in col.addons]`. `collections` is a poor name for a variable btw, clashes with the `collections` module name. – PaulMcG Dec 04 '13 at 21:28