upe*_*upe 60 python python-3.x
是否有一个方便的单行程序来生成 Python 中的数字列表及其负对应项?
例如,假设我想生成一个包含数字 6 到 9 和 -6 到 -9 的列表。
我目前的做法是:
l = [x for x in range(6,10)]
l += [-x for x in l]
Run Code Online (Sandbox Code Playgroud)
一个简单的“单行”将是:
l = [x for x in range(6,10)] + [y for y in range(-9, -5)]
Run Code Online (Sandbox Code Playgroud)
但是,生成两个列表然后将它们连接在一起似乎很不方便。
Dat*_*ice 68
我不确定顺序是否重要,但您可以创建一个元组并将其解压缩到列表理解中。
nums = [y for x in range(6,10) for y in (x,-x)]
print(nums)
[6, -6, 7, -7, 8, -8, 9, -9]
Run Code Online (Sandbox Code Playgroud)
Der*_*nik 64
创建一个漂亮且可读的函数:
def range_with_negatives(start, end):
for x in range(start, end):
yield x
yield -x
Run Code Online (Sandbox Code Playgroud)
用法:
list(range_with_negatives(6, 10))
Run Code Online (Sandbox Code Playgroud)
这就是您为任何东西获得方便的单衬纸的方式。避免试图看起来像一个神奇的职业黑客。
Roa*_*WMC 59
我想说最简单的解决方案是使用*解包运算符将两个范围解包到一个列表中:
>>> [*range(6, 10), *range(-9, -5)]
[6, 7, 8, 9, -9, -8, -7, -6]
Run Code Online (Sandbox Code Playgroud)
这不仅是迄今为止提出的最短答案,而且也是性能最高的答案,因为它只构造一个列表,并且不涉及超出两个ranges 的函数调用。
我通过使用timeit模块测试所有这个问题的答案来验证这一点:
答案 ID 方法 timeit 结果 -------------------------------------------------- ------------------------------------------------ (有问题)[x for x in range(6,10)] + [y for y in range(-9, -5)] 每个循环 0.843 usec (this answer) [*range(6, 10), *range(-9, -5)] 每个循环 0.509 usec 61348876 [y for x in range(6,10) for y in (x,-x)] 每个循环 0.754 微秒 61349149 list(range_with_negatives(6, 10)) 每个循环 0.795 微秒 61348914 list(itertools.chain(range(6, 10), range(-9, -5))) 每个循环 0.709 微秒 61366995 [sign*x 表示符号,x in itertools.product((-1, 1), range(6, 10))] 每个循环 0.899 微秒 61371302 list(range(6, 10)) + list(range(-9, -5)) 每个循环 0.729 微秒 61367180 list(range_with_negs(6, 10)) 每个循环 1.95 微秒
(在我自己的计算机上使用 Python 3.6.9 执行的 timeit 测试(平均规格))
Bar*_*mar 25
You can use itertools.chain() to concatenate the two ranges.
import itertools
list(itertools.chain(range(6, 10), range(-9, -5)))
Run Code Online (Sandbox Code Playgroud)
Fra*_*Vel 10
您可以使用itertools.product,这是笛卡尔积。
[sign*x for sign, x in product((-1, 1), range(6, 10))]
[-6, -7, -8, -9, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
由于您使用乘法,这可能会更慢,但应该易于阅读。
如果您想要一个纯功能的解决方案,您还可以导入itertools.starmap和operator.mul:
from itertools import product, starmap
from operator import mul
list(starmap(mul, product((-1, 1), range(6, 10))))
Run Code Online (Sandbox Code Playgroud)
但是,这不太可读。
Gre*_*ard 10
你真的很接近,结合了两个range对象。但是有一种更简单的方法来做到这一点:
>>> list(range(6, 10)) + list(range(-9, -5))
[6, 7, 8, 9, -9, -8, -7, -6]
Run Code Online (Sandbox Code Playgroud)
即,将每个range对象转换为一个列表,然后将两个列表连接起来。
另一种方法,使用 itertools:
>>> list(itertools.chain(range(6, 10), range(-9, -5)))
[6, 7, 8, 9, -9, -8, -7, -6]
Run Code Online (Sandbox Code Playgroud)
itertools.chain()就像一个广义的+:它不是添加两个列表,而是一个接一个地链接一个迭代器以创建一个“超级迭代器”。然后将它传递给list()你,你会得到一个具体的列表,内存中包含你想要的所有数字。
IMO 在itertools.chain其他几个答案中使用的方法绝对是迄今为止提供的方法中最干净的。
但是,由于在您的情况下,值的顺序无关紧要,因此您可以避免定义两个显式range对象,从而避免执行负range索引所需的所有逐一数学运算,方法是使用itertools.chain.from_iterable:
>>> import itertools
>>> list(itertools.chain.from_iterable((x, -x) for x in range(6, 10)))
[6, -6, 7, -7, 8, -8, 9, -9]
Run Code Online (Sandbox Code Playgroud)
有点冗长,但足够可读。
另一个类似的选择是使用带有 plain 的元组/参数解包chain:
>>> list(itertools.chain(*((x, -x) for x in range(6, 10))))
[6, -6, 7, -7, 8, -8, 9, -9]
Run Code Online (Sandbox Code Playgroud)
更简洁,但我发现元组在快速扫描中更难理解。
权衡另一种可能性。
如果你想要可读性,你原来的单行代码非常好,但我会改变范围,因为我认为负边界会让事情变得不那么清楚。
[x for x in range(6, 10)] + [-x for x in range(6, 10)]
Run Code Online (Sandbox Code Playgroud)
这是一个主题的变体(参见@Derte Trdelnik的回答),遵循itertoolswhere的哲学
迭代器构建块 [...] 可以单独使用或组合使用。
这个想法是,当我们定义一个新函数时,我们不妨让它通用:
def interleaved_negatives(it):
for i in it:
yield i
yield -i
Run Code Online (Sandbox Code Playgroud)
并将其应用于特定的range迭代器:
list(interleaved_negatives(range(6, 10)))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3906 次 |
| 最近记录: |