如果我有一个
然而,是否有一种惯用的(且相对高效)方法来处理迭代器作为输入,并产生一个迭代器(或者可能是流)作为输出? 更新:我有一个工作实现,它实现了Iterator,并在单次遍历中完成了此操作,因此需要很少的内存,但相对较长并使用可变变量(
上面的方法(使用
使用
Seq
,那么生成所有长度不超过给定限制的子序列就很容易了,方法如下:def subseqs[A](n: Int)(s: Seq[A]) = {
(1 to n).flatMap(s.sliding)
}
subseqs(3)(List(1, 2, 3, 4)) foreach println //> List(1)
//| List(2)
//| List(3)
//| List(4)
//| List(1, 2)
//| List(2, 3)
//| List(3, 4)
//| List(1, 2, 3)
//| List(2, 3, 4)
然而,是否有一种惯用的(且相对高效)方法来处理迭代器作为输入,并产生一个迭代器(或者可能是流)作为输出? 更新:我有一个工作实现,它实现了Iterator,并在单次遍历中完成了此操作,因此需要很少的内存,但相对较长并使用可变变量(
var
和ListBuffer
) - 如果有帮助,可以发布此内容。我希望使用高阶函数有一种更优雅的方式...上面的方法(使用
sliding()
)行不通,因为第一次遍历时迭代器已经用尽,不能重新使用。使用
sliding()
和inits()
的组合更好,但会错过预期子序列的尾部:def subseqsi[A](n: Int)(i: Iterator[A]) = {
//(1 to n).flatMap(i.sliding)
// no - this exhausts the iterator
i.sliding(n).flatMap { _.inits.filterNot(_.isEmpty) }
//nearly, this misses off subsequences towards the end
}
//> List(1, 2, 3)
//| List(1, 2)
//| List(1)
//| List(2, 3, 4)
//| List(2, 3)
//| List(2)
我的输入数据是一个大小未知(可能非常大)的迭代器。输出子序列的顺序并不重要。
init . tails <=< tail . inits
可以在有限和无限列表上运行,因此它本质上必须是懒惰的!鱼/<=<
运算符源自Control.Monad
并且是Kleisli组合。 - Mysterious Dan