0

I have something like this:

class C:
  def get_data(): returns a list

d = {several instances of C}

Now, how do I iterate over all elements of all lists? I failed miserably:

[e for e in [v.get_data() for _, v in d.items()]]

The inner loop will produce a list of lists which can not be digested by the outer loop.

Michael
  • 7,407
  • 8
  • 41
  • 84
  • 1
    What is the outer loop doing? Don't you just want `[v.get_data() for v in d.values()]`. What should the output be? Please give a [mcve]. – jonrsharpe May 27 '17 at 11:16
  • If you are using python2.7, I would recommend using iteritems/itervalues, as they require less memory. See this https://stackoverflow.com/questions/13998492/iteritems-in-python. – otadmor May 27 '17 at 11:41

5 Answers5

4

You want a flatten:

[e for _, v in d.items() for e in v.get_data()]

Note the order of the loops.

Dan D.
  • 73,243
  • 15
  • 104
  • 123
3
import itertools

class C:
  def get_data(self): return ['a','b']

d = {'a' : C(), 'b' : C()}

print [e for e in itertools.chain.from_iterable(v.get_data() for v in d.values())]

Will print

['a', 'b', 'a', 'b']
piokuc
  • 25,594
  • 11
  • 72
  • 102
2

Just modify your existing expression -

[item for sublist in [v.get_data() for _, v in d.items()] for item in sublist]
Amey Dahale
  • 750
  • 6
  • 10
1

@piokuc's answer is the better option, but in Python 3, yield from is a possibility:

class C:
    def get_data(self): 
        return ['a','b']


def extract(dict_):
    """Yield elements from sublists."""
    for _, v in dict_.items():
        yield from v.get_data()


d = {'a' : C(), 'b' : C()}
[e for e in extract(d)]
# ['a', 'b', 'a', 'b']
pylang
  • 40,867
  • 14
  • 129
  • 121
0

Not sure what you mean by "iterate over all elements", but based on the code in your question, the following will create a list of all the elements in both Python 2 & 3 and doesn't require importing anything else:

class C:
    def get_data(self): return ['a', 'b']

d = {'a' : C(), 'b' : C()}

print([e for c in d.values() for e in c.get_data()])  # -> ['a', 'b', 'a', 'b']

In Python 2 you might want to use d.itervalues() instead of d.values() because it creates an iterator of the values rather than creating a temporary list of them (which is what Python 3 does automatically when the values() method called).

martineau
  • 119,623
  • 25
  • 170
  • 301