代码优化:while或for(或其他任何东西)?

时间:2014-02-18 13:50:47

标签: python list

我有一个这样的列表(为了简单起见,我使用整数渐进数字,但它们实际上是浮动汇率):

List = [4,5,6,7,8,9,10,11,12]     #__len__ = 9

我需要通过off = 3来“延迟”(偏移)此列表(但这个数字,3,可能是变量),为第一个“off”值添加“0”,然后从“off + 1”开始“列表中的值为”0“:

OffsetList = [0,0,0,4,5,6,7,8,9]   #__len__ = 9

我已经考虑过这两种可能的解决方案,但我对编程很陌生,我希望得到一个人的意见,无论是什么是最优化的解决方案,以及是否可以开发一个不同的解决方案可能比我想到的更好:

#SOLUTION 1
OffsetList = []
for _ in range(0,off):
    OffsetList.append(0)
for k in range(0, len(List) - off):
    OffsetList.append(List[k])

#SOLUTION 2
OffsetList = []
for _ in range(0,off):
    OffsetList.append(0)
j = 0
while len(OffsetList) < len(List):
    OffsetList.append(List[j])
    j += 1

您认为哪一个更优化(快速,安全,稳定等),为什么?另外(我敢肯定),有没有比我想到的更好的解决方案?

5 个答案:

答案 0 :(得分:3)

您可以使用列表切片:

>>> List = [4,5,6,7,8,9,10,11,12]
>>> off = 3
>>> OffsetList = [0]*len(List)
>>> OffsetList[off:] = List[:-off]
>>> OffsetList
[0, 0, 0, 4, 5, 6, 7, 8, 9]

答案 1 :(得分:2)

您可以将列表推导用于此类事情:

List = [4,5,6,7,8,9,10,11,12]
off = 3
OffsetList = [0 for x in xrange(off)] + List[:-off]
print OffsetList

答案 2 :(得分:2)

>>> l = [4,5,6,7,8,9,10,11,12]
>>> off = 3
>>> [0] * off + l[:-off]
[0, 0, 0, 4, 5, 6, 7, 8, 9]

答案 3 :(得分:1)

>>> List = [4,5,6,7,8,9,10,11,12] 
>>> off = 3
>>> OffsetList = [0] * off + List[:-off]
>>> print (OffsetList)

>>> [0, 0, 0, 4, 5, 6, 7, 8, 9]

答案 4 :(得分:1)

最好不要在添加零时显式迭代列表

def prefix1(l, offset):
    return l = [0] * offset + l

def prefix2(l, offset):
    for _ in xrange(offset):
        l.insert(0, 0)
    return l

>>> %timeit prefix1([1,2,3,4,5], 500)
10000 loops, best of 3: 4.87 µs per loop
>>> %timeit prefix2([1,2,3,4,5], 500)
10000 loops, best of 3: 190 µs per loop

Sidenote :我正在使用iPython %timeit魔法,它使用内置的timeit module。您也可以直接调用模块的时间python -m timeit --setup 'n=50;l=[1,2,3,4,5]' 'l = [0] * n + l',但使用iPython可以使事情变得更容易。

通常,Python中的显式循环比列表推导慢,但这并不适用于所有内容,并不意味着您应该尝试将所有内容都写为列表推导。见this article。当看不清楚你想要什么时,我没有看到你为什么要使用while循环的原因,将n元素添加到列表的开头。在这种情况下,我更喜欢准确说明l = [0] * offset + l的意图的代码非常明确。

来自JoelCornett的评论

import itertools

def prefix3(l, offset):
    return list(itertools.chain([0] * offset, l))

def prefix4(l, offset):
    return itertools.chain([0] * offset, l)

def prefix5(l, offset):
    return itertools.chain(itertools.repeat(0, offset), l)

>>> %timeit prefix3([1,2,3,4,5], 500)
10000 loops, best of 3: 13 µs per loop
>>> %timeit prefix4([1,2,3,4,5], 500)
10000 loops, best of 3: 2.9 µs per loop
>>> %timeit prefix5([1,2,3,4,5], 500)
10000 loops, best of 3: 883 ns per loop

请注意,prefix5以纳秒为单位测量,其他为微秒。

prefix3prefix4 & prefix5之间的区别在于itertools.chain返回迭代器(没有随机访问,您无法在其上调用len)。因此,将其转换为prefix3中的列表会产生开销。如果您只想迭代元素而不是按索引访问特定元素,则应使用prefix5,否则prefix2prefix3