pythontupleslist-comprehensioniterable-unpacking

Unpacking tuples in a python list comprehension (cannot use the *-operator)


I am trying to create a list based on another list, with the same values repeated 3 times consecutively.

At the moment, I am using:

>>> my_list = [ 1, 2 ]
>>> three_times = []
>>> for i in range( len( my_list ) ):
...   for j in range( 3 ):
...     three_times.append( my_list[ i ] )
...
>>> print three_times
[1, 1, 1, 2, 2, 2]

But I would like to do it using a more Pythonic way, such as:

>>> my_list = [ 1, 2 ]
>>> three_times = []
>>> three_times = [ (value,) * 3 for value in my_list ]
>>> print(three_times)
[(1, 1, 1), (2, 2, 2)]

However, I cannot find a way to unpack the tuples.

Something like three_times = [ *( (value,) * 3 ) for value in my_list ] would be perfect for unpacking the tuples but this is not a correct syntax.


Solution

  • You can't use * iterable unpacking in a list comprehension, that syntax is only available in calls, and in Python 3, when using assignments.

    If you want to use a list comprehension, just put your for loops in series; you do want to access the values from my_list directly rather than generate indices though:

    [v for v in my_list for _ in range(3)]
    

    There are several other options too:

    • Use itertools.repeat() to repeat the values, and itertools.chain.from_iterable() to concatenate those iterators back together: chain.from_iterable(repeat(v, 3) for v in my_list). That produces an iterator, you can use list() on it to get a list again.
    • Use chain.from_iterable(zip(*([my_list] * 3))) to create an iterator over the repeated values (the repeated list is transposed into repeated columns). This is not nearly as readable, of course, but we could make it slightly less bad by using repeat() here too: chain.from_iterable(zip(*repeat(my_list, 3))). Again, use list() to produce the same output as the list comprehension.