使用 enumerate() 和 takewhile() 到 return python 中的列表

Using enumerate() and takewhile() to return a list in python

我正在尝试使用 enumerate() 和 takewhile() 为 return 斐波那契生成器的前 n 个元素的列表定义一个方法。我的代码进入无限循环并且从不检查 takewhile() 中的条件以停止迭代。我知道 islice() 更容易,但我只需要使用 enumerate 和 takewhile 来定义方法。

from itertools import takewhile


def fibonacci_unbounded():
    (a, b) = (0, 1)
    while True:
        yield a
        (a, b) = (b, a + b)


def take_e(n, gen):
    fib_list = []
    for (i, elem) in enumerate(gen):
        if takewhile(i < n, gen):
            fib_list.append(elem)
        else:
            return fib_list


fibonacci = fibonacci_unbounded
n = 8

print(take_e(n, fibonacci()))

这是一种行之有效的方法。我希望找到一种不需要将索引添加到逻辑中的方法,以便您可以测试返回的“第 n 个”项目:

def fibonacci_unbounded():
    (a, b) = (0, 1)
    while True:
        yield a
        (a, b) = (b, a + b)

def take_e(n, gen):
    return [x[1] for x in takewhile(lambda x: x[0] < n, enumerate(gen()))]

print(take_e(9, fibonacci_unbounded))

结果:

[0, 1, 1, 2, 3, 5, 8, 13, 21]

如果我不必使用 takewhile 会更简单。我以前从未使用过它,所以我不知道使用它是否有特殊技巧。将您想要的计数传递给基础斐波那契生成器并让它在适当的时刻停止会更容易。

当您使用 range 迭代器时,

zip 的工作方式与 enumerate 非常相似。好的部分是 zip 在最短的迭代中停止。所以放弃 takewhile 并使用在正确位置停止的枚举器。

def fibonacci_unbounded():
    (a, b) = (0, 1)
    while True:
        yield a
        (a, b) = (b, a + b)

def take_e(n, gen):
    return list((elem) for _,elem in zip(range(n), gen))

fibonacci = fibonacci_unbounded
n = 8
print(take_e(n, fibonacci()))

如果需要使用 takewhileenumerate,您应该从枚举中获取值,直到满足条件。

from itertools import takewhile

def fibonacci_unbounded():
    (a, b) = (0, 1)
    while True:
        yield a
        (a, b) = (b, a + b)

def take_e(n, gen):
    return list(val for _,val in takewhile(
        lambda i_val: i_val[0] < n, enumerate(gen)))

fibonacci = fibonacci_unbounded
n = 8
print(take_e(n, fibonacci()))