5

Why does the below list comprehension give an error? What am I missing?

a = [
[(1, 2), (11, 22), (111, 222)],
[(3, 4), (33, 44), (333, 444)],
[(5, 6), (55, 66), (555, 666)]
]

b = [k for k in j for j in i for i in a]
print(sorted(b))

I know there are more elegant/readable solutions, but this is for my own understanding.

Error: TypeError: 'int' object is not iterable

Desired Output: [1, 2, 3, 4, 5, 6, 11, 22, 33, 44, 55, 66, 111, 222, 333, 444, 555, 666]

Josh Friedlander
  • 10,870
  • 5
  • 35
  • 75
alwayscurious
  • 1,155
  • 1
  • 8
  • 18
  • Possible duplicate of [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) – mkrieger1 Feb 26 '19 at 10:53

2 Answers2

3

The order in the list comprehension is wrong. Here is the correct solution:

In [5]: a = [
   ...: [(1, 2), (11, 22), (111, 222)],
   ...: [(3, 4), (33, 44), (333, 444)],
   ...: [(5, 6), (55, 66), (555, 666)]
   ...: ]
   ...: 
   ...: b = [j for x in a for y in x for j in y]
   ...: 
   ...: 
   ...: 

In [6]: 

In [6]: b
Out[6]: [1, 2, 11, 22, 111, 222, 3, 4, 33, 44, 333, 444, 5, 6, 55, 66, 555, 666]

In [7]: sorted(b) 
Out[7]: [1, 2, 3, 4, 5, 6, 11, 22, 33, 44, 55, 66, 111, 222, 333, 444, 555, 666]

Here is an SO discussion that explains nested list comprehension: Explanation of how nested list comprehension works?

Mohamed Ali JAMAOUI
  • 14,275
  • 14
  • 73
  • 117
3

One way to think about nested list comprehensions is to imagine them written out as a loop, and then scoop them up from top to bottom, finally using the last line at the beginning (since this is what we want to print). This way each variable is declared in memory, starting from the known and moving on to each temporary level.

So if we have:

for sublist in a:
    for tup in sublist:
        for item in tup:
            print(item)

We could rewrite this as

[print(item) for sublist in a for tup in sublist for item in tup]

> [1, 2, 11, 22, 111, 222, 3, 4, 33, 44, 333, 444, 5, 6, 55, 66, 555, 666]

(and so on ad infinitum)

Josh Friedlander
  • 10,870
  • 5
  • 35
  • 75