2

I have a list of tuples, with each tuple containing a tuple pair, coordinates.

list1 = [((11, 11), (12, 12)), ((21, 21), (22, 22)), ((31,31), (32,32))] # list of tuple pairs

Using list comprehension I am trying to generate a list without them being paired but still in the same order. I was able to get the result be looping and using .append() but I was trying to avoid this.

new_list = []
for i in list1:
    for x in i:
        new_list.append(x)

print(new_list)

output:

[(11, 11), (12, 12), (21, 21), (22, 22), (31, 31), (32, 32)]

this works and gives me the result I am looking for:

But when I try list comprehension I get the last tuple pair repeated!

new_list = [x for x in i for i in list1]

print(new_list)

output:

[(31, 31), (31, 31), (31, 31), (32, 32), (32, 32), (32, 32)]

I am sure it is a small thing I am doing wrong so would appreciate the help!!

Moinuddin Quadri
  • 46,825
  • 13
  • 96
  • 126
Eoin Brennan
  • 131
  • 7
  • 2
    `[t for vals in list1 for t in vals]` should give the expected output. Read more about [Nested for loop list comprehension](https://stackoverflow.com/questions/3633140/nested-for-loops-using-list-comprehension) – Ch3steR Feb 05 '22 at 13:28
  • Does this answer your question? [How to make a flat list out of a list of lists?](https://stackoverflow.com/questions/952914/how-to-make-a-flat-list-out-of-a-list-of-lists) – Max Feb 05 '22 at 13:30
  • Could discard the last element: `new_list = [x for x in i for i in list1][:-1]` – Jack Deeth Feb 05 '22 at 13:33
  • 1
    Didn't you ask this question 1 hour ago today ? https://stackoverflow.com/q/70997748/13944524 – S.B Feb 05 '22 at 13:39
  • The left-to-right ordering of generators in a list comprehension should match the top-to-bottom ordering of iterators in a nested for loop. – chepner Feb 05 '22 at 14:02
  • 1
    That is, write your for loops on one line then move the body of the inner loop to the front of the expression, drop the `:`s, wrap it all in `[...]`, and call it a day. – chepner Feb 05 '22 at 14:03
  • Yea, posted this an hour previous but thought I messed up on formating the post to show the code properly so deleted I thought! and reposted properly!! – Eoin Brennan Feb 06 '22 at 09:47

3 Answers3

2

Python is having inbuilt function itertools.chain.from_iterable() to achieve the same result:

>>> from itertools import chain
>>> my_list = [((11, 11), (12, 12)), ((21, 21), (22, 22)), ((31,31), (32,32))]


>>> list(chain.from_iterable(my_list))  # OR, list(chain(*my_list))
[(11, 11), (12, 12), (21, 21), (22, 22), (31, 31), (32, 32)]
Moinuddin Quadri
  • 46,825
  • 13
  • 96
  • 126
1

Use Alex Martelli's method to flatten a list of lists by one level:

>>> [t for tt in list1 for t in tt]
[(11, 11), (12, 12), (21, 21), (22, 22), (31, 31), (32, 32)]
dawg
  • 98,345
  • 23
  • 131
  • 206
1

This should give you the expected output:

flat_list1 = [result_tuple for coupled_tuples in list1 for result_tuple in coupled_tuples]

Like in your question - where you looped over list1 and then each of it's tuple elements, for coupled_tuples in list1 is the outer loop, for result_tuple in coupled_tuples is the inner loop.

You can have as many independent for x in y clauses as you want in a comprehension just by sticking one after the other.

flat_list1 = [
              result_tuple                       # result
              for coupled_tuples in list1        # outer for loop
              for result_tuple in coupled_tuples # inner for loop
             ]