3

List comprehensions are great. Is there an elegant, slick way to do a list comprehension that appends items to each other as they go, rather than putting them all in a list?

IE, I have some comprehension [func(x) for x in y if z] that spits out [['a','b'],['c','d'],['e','f']], what can i write to instead spit out ['a','b','c','d','e','f']?

Obviously I could do

alist = []

for x in y:
    if z:
        alist += func(x)

but that's four or five lines of code! it feels like there must be a way to do it that's as simple and easy as the list comprehension is.

Skaramuche
  • 87
  • 4
  • Related [How to make a flat list out of list of lists?](https://stackoverflow.com/questions/952914/how-to-make-a-flat-list-out-of-list-of-lists) – Tomerikoo Dec 07 '20 at 21:20

2 Answers2

6
[elem for x in y if z for elem in func(x)]

Just add another layer of iteration.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • 1
    [Here](https://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/) is a useful resource for understanding multi-layered list comprehensions. – Karl Knechtel Dec 07 '20 at 07:24
1

This question isn't specific to list comprehensions; it has to do with flattening of nested containers or iterables in general. (That would include, list, tuple, set, etc.)

Unlike some sloppier programming languages — cough whose names also start with “P” cough — Python never implicitly flattens nested containers.

The standard-library Pythonic way to flatten a nested container is with itertools.chain, which works as a generator and thus avoids making unnecessary intermediary copies of the list, or whatever iterable you pass it. There are two ways to invoke it:

  • chain(iterable1, iterable2, …): for example, list(chain([1,2],[3,4]))[1, 2, 3, 4]
  • chain.from_iterable(iterable_of_iterables): for example, l = [[1, 2], [3, 4]]; list(chain.from_iterable(l))[1, 2, 3, 4]

For your specific example:

from itertools import chain

# Your starting case:
l = [['a','b'],['c','d'],['e','f']]

# This is now an iterator, not a list
it = chain.from_iterable(l)

# Make it back into a list
l2 = list(it)

# Prints:
#   ['a', 'b', 'c', 'd', 'e', 'f']
print(l2)
user2357112
  • 260,549
  • 28
  • 431
  • 505
Dan Lenski
  • 76,929
  • 13
  • 76
  • 124