Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 351
DRz Avatar asked May 17 '16 14:05

DRz


People also ask

Does * unpack list Python?

Unpacking assigns elements of the list to multiple variables. Use the asterisk (*) in front of a variable like this *variable_name to pack the leftover elements of a list into another list.

How do I unpack a list of tuples in Python?

Python uses the commas ( , ) to define a tuple, not parentheses. Unpacking tuples means assigning individual elements of a tuple to multiple variables. Use the * operator to assign remaining elements of an unpacking assignment into a list and assign it to a variable.

Does tuple unpacking work with lists?

In Python, unpacking is not limited to tuples only. You can unpack a list or a string with the same syntax. Unpacking is more commonly known as multiple assignment, as it reminds of assigning multiple variables on the same line.

How does tuple unpacking work in Python?

When we are unpacking values into variables using tuple unpacking, the number of variables on the left side tuple must exactly match the number of values on the right side tuple . Otherwise, we'll get a ValueError .

How to unpack tuples in Python?

Unpacking tuples means assigning individual elements of a tuple to multiple variables. Use the * operator to assign remaining elements of an unpacking assignment into a list and assign it to a variable. Did you find this tutorial helpful ?

What is the unpacking operator in Python?

Sure there is, and it’s called unpacking operator or asterisk operator (*, **). Let’s see how to use it in Python. The asterisk operator (*) is used to unpack all the values of an iterable that have not been assigned yet.

What is unpacking a tuple of variables?

This is called "unpacking": Note: The number of variables must match the number of values in the tuple, if not, you must use an asterisk to collect the remaining values as a list. If the number of variables is less than the number of values, you can add an * to the variable name and the values will be assigned to the variable as a list:

How to define a tuple with only one element in Python?

To define a tuple with only one element, you still need to use a comma. The following example illustrates how to define a tuple with one element: It’s equivalent to the following: Note that the following is an integer, not a tuple: Unpacking a tuple means splitting the tuple’s elements into individual variables. For example:


Video Answer


2 Answers

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)] 
like image 177
Martijn Pieters Avatar answered Sep 20 '22 19:09

Martijn Pieters


Accepted answer is correct, but I made some efficiency tests, so sharing it for passers-by.

Summary: Use chain.from_iterable for ~x2 speed improvement over list comprehension. And use np.repeat for ~x6 speed improvement if you don't mind importing numpy, but don't use np.repeat if eventually converting back to list.

In [1]: from itertools import chain    ...: import numpy as np    ...:     ...: def nested_list_comprehension(seq, repeats):    ...:     return [v for v in seq for _ in range(repeats)]    ...:     ...: def chain_from_iterable_tuple(seq, repeats):    ...:     return list(chain.from_iterable((v,) * repeats for v in seq))    ...:     ...: def chain_from_iterable_list(seq, repeats):    ...:     return list(chain.from_iterable([v] * repeats for v in seq))    ...:     ...: def numpy_repeat_list(seq, repeats):    ...:     return list(np.repeat(seq, repeats))    ...:     ...: def numpy_repeat(seq, repeats):    ...:     return np.repeat(seq, repeats)  In [2]: seq = list(range(1000))    ...: repeats = 100  In [3]: assert (    ...:     nested_list_comprehension(seq, repeats)    ...:     == chain_from_iterable_tuple(seq, repeats)    ...:     == chain_from_iterable_list(seq, repeats)    ...:     == numpy_repeat_list(seq, repeats)    ...: )  In [4]: %timeit nested_list_comprehension(seq, repeats)    ...: %timeit chain_from_iterable_tuple(seq, repeats)    ...: %timeit chain_from_iterable_list(seq, repeats)    ...: %timeit numpy_repeat_list(seq, repeats)    ...: %timeit numpy_repeat(seq, repeats) 1.53 ms ± 2.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 814 µs ± 3.79 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 842 µs ± 2.02 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 3.65 ms ± 22.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 268 µs ± 1.44 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 
like image 33
paime Avatar answered Sep 20 '22 19:09

paime