簡體   English   中英

如何循環 Python 列表以將其從 M 擴展到 N 值(M < N)?

[英]How do you cycle a Python list to extend it from M to N values (M < N)?

我有一個元素列表 N,我想重復遍歷它直到它有 M 個元素,其中 M 可以是任何 integer,不一定是 N 的 integer 倍數。

我找到了兩種方法來做到這一點,但似乎都沒有我想象的那么直接。 在 Python 中有沒有更原生的方法來做到這一點?

這是我想出的。 請注意,第一種方法在有限的測試中更快。

from math import ceil

def repeat_list_1(values, n):
    repeated = values * ceil(n / len(values))
    return repeated[:n]
from itertools import cycle

def repeat_list_2(values, n):
    values_cycler = cycle(values)
    repeated = [next(values_cycler) for _ in range(n)]
    return repeated
values = list(range(5))
n = 12
repeated1 = repeat_list_1(values, n)
repeated2 = repeat_list_2(values, n)
assert repeated1 == repeated2
print(repeated1)
[0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2]

如前所述,有多種方法可以實現這一目標,您必須根據一些標准(速度、代碼簡單性......)選擇您最喜歡的一種。

這是我覺得很簡單的一個(雖然它是舊式的 - 它不使用生成器):

 >>> def repeat_list_4(values, n): ... d, m = divmod(n, len(values))... return values * d + values[:m]... >>> >>> repeat_list_4(list(range(5)), 12) [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1] >>> repeat_list_4(list(range(5)), 5) [0, 1, 2, 3, 4] >>> repeat_list_4(list(range(5)), 1) [0] >>> repeat_list_4(list(range(5)), 0) []

作為旁注,在您的示例中有n = 12 ,但結果列表有13 個元素。

您可以使用islice獲取可迭代的前n值(在某些其他語言中稱為take ):

from itertools import cycle, islice

def repeat_list_3(values, n):
    return list(islice(cycle(values), n))

我不知道這是否有效,但你可以這樣做。

l = [0, 1, 2, 3, 4]
N = 12
k = (l * (N // len(l) + len(l) - N % len(l)))[:N]

print(k)
# [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1]

首先,您將列表擴展到N + k個術語,其中N + klen(l)的因子。 最后對結果列表進行切片以獲得N個元素。

numpy 有一個方便的 function:

np.resize(values, n)

但您需要將其從np.ndarray轉換回list

我已經使用 zip() 在循環遍歷列表時定義了一個限制。

使用 itertools 的示例:

from itertools import cycle


values = ['a', 'b', 'c', 1]
n = 10

pool = cycle(values)

for item, limit in zip(pool, range(n)):
    print(item)

在不導入的情況下執行此操作的一種方法是在不使用 itertools 的情況下循環迭代,這可以使用生成器輕松完成。

values = ['a', 'b', 'c', 1]

def circular():
    while True:
        for connection in values:
            yield connection

n = 10

for item, limit in zip(circular(), range(n)):
    print(item)

然而,我確實認為這個解決方案很笨重,並且不使用 zip() ,因為它打算使用。

我還從您的第二個示例中獲取了代碼,並用生成器替換了循環,以避免導入任何內容。

values = ['a', 'b', 'c', 1]
n = 10

def circular():
    while True:
        for connection in values:
            yield connection


def repeat_list_2(values, n):
    values_cycler = circular()
    repeated = [next(values_cycler) for _ in range(n)]
    return repeated

print(repeat_list_2(values, n))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM