大多数pythonic方式将列表扩展到一定长度?

时间:2014-06-05 17:54:56

标签: python

我的目标是获取未知数量的元素列表,并将其扩展/切片到精确的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方式吗?


编辑:澄清一点,我不是要修改原始数组,我正在返回一个可能是浅层副本的新数组。

6 个答案:

答案 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:]