Python:在一个列表中移动元素,使其长度恒定

2mbi3lxu  于 2023-04-10  发布在  Python
关注(0)|答案(7)|浏览(120)

我正在寻找一种优雅的方式来编写一个简单的函数,该函数将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

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

ruarlubt

ruarlubt1#

我会使用slice赋值:

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
bogh5gae

bogh5gae2#

如果你可以使用双端队列而不是列表,它有一些很好的特性,使它成为解决这个问题的自然选择。从双端队列的左边工作比在列表上工作要便宜得多。而且它有一个maxlen参数,可以用来使代码更漂亮,更快。我很确定使用itertools.repeat而不是[empty] * n更有效。无论是内存方面还是速度方面。

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

wydwbb8l

wydwbb8l3#

有点天真,但工作完成了。

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
rpppsulh

rpppsulh4#

旋转列表的非直观方式

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))
cotxawn7

cotxawn75#

我会这样做:

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

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

fhity93d6#

这样行吗

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

xfb7svmp7#

下面的方法没有回答这个问题,但我仍然发现它对那些想像圆一样移动valuse的人很有帮助。

# Shift to the left.
shift = 1
a = [1, 2, 3, 4]
a = a[shift:] + a[:shift]
# [2, 3, 4, 1]

# Shift to the right.
shift = -1
a = [1, 2, 3, 4]
a = a[shift:] + a[:shift]
# [4, 1, 2, 3]

相关问题