从Swift中的无限迭代器或生成器获取前N个元素

时间:2019-07-06 13:37:32

标签: python swift iterator generator

我在Python中经常使用生成器。现在我尝试在Swift中做类似的事情。

使用Python中的无限阶乘生成器。

(0,0,0)

一个Swift版本应该是

mesh.postion

我通过使用前四个元素进行测试

def gen_factorial():
  current = 1
  N = 1
  while True:
    yield current
    N += 1
    current *= N

并按预期获得struct gen_factorial: Sequence, IteratorProtocol { var current = 1 var N = 1 mutating func next()-> Int?{ defer { N += 1 current *= N } return current } }

但是当我想编写一个辅助函数zip(1...4, gen_factorial() ).map{$1} 来简化它时,我做不到。

1, 2, 6, 24

错误消息是

take(n, gen)

如果不是AnyIterator,func take(_ n: Int, _ it: AnyIterator<Int>) -> [Int]{ return zip(1...n, it).map {$1} } take(4, gen_factorial()) 应该是什么类型?

我还是Swift的新手。请帮忙。

1 个答案:

答案 0 :(得分:2)

AnyIterator concrete 类型,符合Iterator(和Sequence)协议。为了将迭代器传递给该函数,您必须将其包装到AnyIterator中:

print(take(4, AnyIterator(gen_factorial())))
// [1, 2, 6, 24]

更好的解决方案是使函数 generic 使其具有任意序列类型作为参数:

func take<S: Sequence>(_ n: Int, _ it: S) -> [S.Element]{
    return zip(1...n, it).map {$1}
}

print(take(4, gen_factorial()))
// [1, 2, 6, 24]

备注:

  • 您可以使用Sequence的现有prefix(_ maxLength:)方法来代替您的助手功能:

    print(Array(gen_factorial().prefix(4)))
    // [1, 2, 6, 24]
    
  • 类型为大写驼峰的Swift命名约定。