小能豆

在 Python 中对列表进行切片而不生成副本

javascript

给定一个整数列表L,我需要生成所有子列表L[k:] for k in [0, len(L) - 1],而不生成副本。

我如何在 Python 中实现这一点?使用缓冲区对象?


阅读 37

收藏
2024-08-28

共1个答案

小能豆

在 Python 中,您可以使用切片L[k:]为 all kin生成子列表[0, len(L) - 1],而无需生成副本,因为 Python 中的切片会返回列表的新视图,而不是元素的副本。但是,如果您想避免切片的开销,或者想要尽可能接近地模拟此行为而不复制元素,则可以使用带索引的循环或使用itertools.islice。以下是方法:

1. 使用列表切片(无显式复制)

切片列表不会复制底层元素,但会创建一个引用相同元素的新列表对象。这种方法通常很高效,而且很 Pythonic。

L = [1, 2, 3, 4, 5]

# Generate sublists
sublists = [L[k:] for k in range(len(L))]

for sublist in sublists:
    print(sublist)

2. 使用生成器生成子列表

您可以使用生成器来延迟生成子列表:

def sublists(L):
    for k in range(len(L)):
        yield L[k:]

# Usage
L = [1, 2, 3, 4, 5]
for sublist in sublists(L):
    print(sublist)

3. 使用itertools.islice

itertools.islice可用于创建一个迭代器,以惰性方式生成列表的切片:

from itertools import islice

def sublists(L):
    for k in range(len(L)):
        yield islice(L, k, None)

# Usage
L = [1, 2, 3, 4, 5]
for sublist in sublists(L):
    print(list(sublist))  # Convert to list to print, but the iteration itself is lazy

4. 使用memoryview(仅适用于字节列表)

bytes如果您的列表由字节(即或对象)组成bytearray,则您可以使用它memoryview在列表中创建视图而无需复制:

L = bytearray([1, 2, 3, 4, 5])

def sublists(L):
    mv = memoryview(L)
    for k in range(len(L)):
        yield mv[k:]

# Usage
for sublist in sublists(L):
    print(bytes(sublist))  # Convert to bytes to print, but the view is lazy

结论

对于一般列表,使用切片或生成器(如方法 1 和 2 中所示)通常是最佳方法。itertools.islice是避免创建中间列表的另一个不错的选择。如果您的列表专门由字节组成,则memoryview可能是一种有效的选择。

在所有情况下,都不会复制基础数据,并且您仅通过引用现有数据来生成子列表。

2024-08-28