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

2024-10-03 23:23:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Python中经常使用生成器。现在我试着用Swift做类似的事情。你知道吗

来自Python中的无限阶乘生成器。你知道吗

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)来简化它时,我不能

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

take(4, gen_factorial())

错误消息是

error: cannot convert value of type 'gen_factorial' to expected argument type 'AnyIterator<Int>'

如果不是迭代器,it应该是什么类型?你知道吗

我对斯威夫特还是个新手。请帮忙。你知道吗


Tags: mapreturnvartypeitcurrentzip事情
1条回答
网友
1楼 · 发布于 2024-10-03 23:23:45

AnyIterator是一种符合Iterator(和Sequence)协议的具体类型。为了将迭代器传递给该函数,必须将其包装成AnyIterator

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

更好的解决方案是使函数泛型,使其以任意序列类型作为参数:

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的现有^{}方法来代替helper函数:

    print(Array(gen_factorial().prefix(4)))
    // [1, 2, 6, 24]
    
  • 类型的Swift命名约定是一个大写的camel大小写。

相关问题 更多 >