Python:在列表中移动具有恒定长度的元素

时间:2012-02-09 11:24:33

标签: python list

我正在寻找一种优雅的方法来编写一个简单的函数,该函数将列表的元素移动给定数量的位置,同时保持相同长度的列表并用默认值填充空位置。这将是函数的文档字符串:

def shift_list(l, shift, empty=0):
    """
    Shifts the elements of a list **l** of **shift** positions,
    padding new items with **empty**::

        >>> l = [0, 1, 4, 5, 7, 0]
        >>> shift_list(l, 3)
        [0, 0, 0, 0, 1, 4]
        >>> shift_list(l, -3)
        [5, 7, 0, 0, 0, 0]
        >>> shift_list(l, -8)
        [0, 0, 0, 0, 0, 0]
    """
    pass

你会怎么做?任何帮助非常感谢!

6 个答案:

答案 0 :(得分:3)

我使用切片分配:

def shift_list(l, shift, empty=0):
    src_index = max(-shift, 0)
    dst_index = max(shift, 0)
    length = max(len(l) - abs(shift), 0)
    new_l = [empty] * len(l)
    new_l[dst_index:dst_index + length] = l[src_index:src_index + length]
    return new_l

答案 1 :(得分:2)

如果您可以使用deque而不是列表,它有一些很好的功能,使其成为此问题的自然选择。在双端队列左侧工作比在列表上这样做要便宜得多。它还有maxlen argument,可用于使代码更漂亮,更快。我相信使用itertools.repeat而不是[empty] * n更有效率,包括内存wize和速度。

from collections import deque
from itertools import repeat

def shift_list(l, n, empty=0):
    d = deque(l, maxlen=len(l))
    if n > 0:
        d.extendleft(repeat(empty, min(n, len(l))))
    elif n < 0:
        d.extend(repeat(empty, min(-n, len(l))))
    # return list(d) to pass your doctest, at the cost of performance
    return d   

虽然有点警告 - 虽然迭代双端队列元素的时间复杂度与列表中的相同,但是项目查找可能相当昂贵 - 这取决于在索引上:s[0]s[-1]非常快,s[len(s)/2]是最贵的。因此,如果您进行大量查找,请考虑使用其他解决方案,或将结果转换回列表。有关概述,请参阅this page

答案 2 :(得分:1)

有点天真,但工作已经完成。

def shift(l, shift, empty=0):
    reverse = False
    if shift < 0:
        reverse = True
        shift = abs(shift)
    while (shift > 0) :
        if reverse:
            l.pop(0)
            l.append(empty)
        else:
            l.pop()
            l.insert(0, empty)
        shift-=1



l = [0, 1, 4, 5, 7, 0]
shift(l, 3)
print l
l = [0, 1, 4, 5, 7, 0]
shift(l, -3)
print l
l = [0, 1, 4, 5, 7, 0]
shift(l, -8)
print l

答案 3 :(得分:1)

旋转列表的非直观方式

def shift_list(l, shift, empty=0):
    l1=[empty]*len(l)+l+[empty]*len(l)
    l1=l1[len(l)-shift:][0:len(l)]
    return l1+[empty]*(len(l)-len(l1))

答案 4 :(得分:0)

会这样做吗?

def shift_list(l, shift, empty=0):
    while shift > 0:
        l.insert(0,empty)
        l.pop()
        shift -= 1
    ​return l

答案 5 :(得分:0)

我会这样做:

def shift_list(l, shift, empty=0):
    if shift > 0:
        return [empty] * shift + l[:-shift]

    return l[-shift:] + [empty] * abs(shift)