在 python 列表理解中解包元组(不能使用 *-operator)
Unpacking tuples in a python list comprehension (cannot use the *-operator)
我正在尝试基于另一个列表创建一个列表,其中相同的值连续重复 3 次。
目前,我正在使用:
>>> 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]
但我想用更 Pythonic 的方式来做,例如:
>>> my_list = [ 1, 2 ]
>>> three_times = []
>>> three_times = [ (value,) * 3 for value in my_list ]
>>> print three_times
[(1, 1, 1), (2, 2, 2)]
但是,我找不到解包元组的方法。
three_times = [ *( (value,) * 3 ) for value in my_list ]
之类的东西非常适合解包元组,但这不是正确的语法。
您不能在列表理解中使用 *
可迭代解包,该语法仅在调用中可用,并且在 Python 3 中使用赋值时可用。
如果你想使用列表理解,只需将你的 for
循环串联起来;你确实想直接从 my_list
访问值而不是生成索引:
[v for v in my_list for _ in range(3)]
接受的答案是正确的,但我做了一些效率测试,所以分享给路人。
总结: 使用 chain.from_iterable
比列表理解提高 ~x2 速度。如果您不介意导入 numpy
,请使用 np.repeat
提高 ~x6 速度,但如果最终转换回 ,请不要 使用 np.repeat
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)
我正在尝试基于另一个列表创建一个列表,其中相同的值连续重复 3 次。
目前,我正在使用:
>>> 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]
但我想用更 Pythonic 的方式来做,例如:
>>> my_list = [ 1, 2 ]
>>> three_times = []
>>> three_times = [ (value,) * 3 for value in my_list ]
>>> print three_times
[(1, 1, 1), (2, 2, 2)]
但是,我找不到解包元组的方法。
three_times = [ *( (value,) * 3 ) for value in my_list ]
之类的东西非常适合解包元组,但这不是正确的语法。
您不能在列表理解中使用 *
可迭代解包,该语法仅在调用中可用,并且在 Python 3 中使用赋值时可用。
如果你想使用列表理解,只需将你的 for
循环串联起来;你确实想直接从 my_list
访问值而不是生成索引:
[v for v in my_list for _ in range(3)]
接受的答案是正确的,但我做了一些效率测试,所以分享给路人。
总结: 使用 chain.from_iterable
比列表理解提高 ~x2 速度。如果您不介意导入 numpy
,请使用 np.repeat
提高 ~x6 速度,但如果最终转换回 ,请不要 使用 np.repeat
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)