我的目标是获取未知数量的元素列表,并将其扩展/切片到精确的n
元素,填充列表太短而0
和切片列表太长。< / p>
例如
n = 10
foo = [1,2,3,4]
print some_func(foo,n)
应该返回[1,2,3,4,0,0,0,0,0,0]
和
n = 10
foo = [1,2,3,4,5,6,7,8,9,10,11,12]
print some_func(foo,n)
应该返回[1,2,3,4,5,6,7,8,9,10]
现在我正在这样做:
def some_function(l, n):
l.extend([0] * n)
l = l[:n]
return l
但这似乎效率低下。有更多的pythonic方式吗?
编辑:澄清一点,我不是要修改原始数组,我正在返回一个可能是浅层副本的新数组。
答案 0 :(得分:5)
构建比您需要的更大的列表是非常低效的(特别是如果n
变大);相反,只需添加您需要的填充。此外,如果函数在适当的位置更改其参数,则return None
为Python约定:
def some_func(l, n, pad=0):
if len(l) >= n:
del l[n:]
else:
l.extend([pad] * (n - len(l)))
示例:
>>> l = [1, 2, 3, 4, 5]
>>> some_func(l, 3)
>>> l
[1, 2, 3]
>>> some_func(l, 5)
>>> l
[1, 2, 3, 0, 0]
或者,return
新列表:
def some_func(l, n, pad=0):
if len(l) >= n:
return l[:n]
return l + ([pad] * (n - len(l)))
答案 1 :(得分:4)
唯一潜在的&#34;更多Pythonic&#34;这样做的方法几乎就是你拥有它的方式,但是跳过额外的变量分配并直接返回结果。您还可以使用函数和变量名称明确使conforming to PEP8更具Pythonic。
除此之外,您可以通过添加尽可能多的零来提高效率,而不是构建太长的列表然后修剪它。
def pad_or_truncate(some_list, target_len):
return some_list[:target_len] + [0]*(target_len - len(some_list))
分解,这里有两种情况(折扣输入恰好是正确长度的普通情况)。列表太长,或列表太短。
如果列表太长,我们只是将其切片。 some_list[:target_len]
负责照顾。由于切片操作很友好,如果目标长度超出列表的实际长度,则不会爆炸。
如果列表太短,我们用零填充它。我选择通过乘以列表文字 1 来做到这一点,但你可以使用与 2 完全相同的列表理解,如果这更像是你的一杯茶。只需确定要添加多少个零(如果列表不太短,或者为target_len - len(some_list)
,则为零),并连接由多个零组成的列表。做完了!
如果您想使其成为就地操作(因为您的原始示例似乎是尝试但未能实现;请参阅@ chepner&#39;评论),您只需更改{ {1}}至return <...>
。
1 一些简短的some_list[:] = <...>
结果表明,字面乘法比列表理解隐含的双重迭代要快一些。
2 对于后代,列表理解版本看起来像:
timeit
答案 2 :(得分:1)
islice
如何使用填充生成器连接原始列表?
from itertools import islice, repeat
def fit_to_size(l, n):
return list(islice(
( x
for itr in (l, repeat(0))
for x in itr ),
n))
您可能更喜欢这种稍微更明确的实现:
def fit_to_size(l, n):
def gen():
yield from l
while True: yield 0
return list(islice(gen(), n))
答案 3 :(得分:1)
为什么不使用条件逻辑?
def pad_or_slice(L, n):
if len(L) < n:
return L + ([0] * (n - len(L)))
else:
return L[:n]
这样你只需要检查两个中的一个,而不是两个,而不是检查列表的长度,这不应该太昂贵。
答案 4 :(得分:0)
效率并不高,但我会做l = (l + [0] * (n - len(l)))[:n]
。所以你的some_function
看起来像这样
def some_function(list, n):
return (list + [0] * (n - len(list)))[:n]
答案 5 :(得分:0)
为了正确修改原始列表,您需要从对象中删除尾随切片。
def some_function(l, n):
l.extend([0] * n)
del l[n:]