Kotlin提供了take
和takeWhile
方法,让人们可以获取n
的第一个Sequence<T>
项,并将它们作为另一个序列单独处理,例如{{1}其中一些,drop
与其他值等。
但是当我使用map
和take
时,序列的尾部就会被删除。
现在,给定一个一次约束的序列,如何将其任意前缀转换为保留尾部的另一个序列(如果它仍然存在)?
示例:
takeWhile
如何为多个前缀执行相同操作?
示例:
val seq = (1..10).asSequence().constrainOnce()
// emits 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
val modified = seq.changePrefix { take(5).map { -1 * it } }
// emits -1, -2, -3, -4, -5, 6, 7, 8, 9, 10
注意:问题是有意提出的answered by the author。
答案 0 :(得分:3)
如果val seq = (1..10).asSequence().constrainOnce()
val modified = seq.changePrefixes(
{ take(3).map { it * -1 } },
{ drop(1).take(3).map { it * 100 } },
{ map { 0 } }
)
//emits -1, -2, -3, 500, 600, 700, 0, 0, 0
曾被约束,则意味着不允许从中创建多个Sequence<T>
。因此,解决方案是创建一个迭代器并从中生成更改的前缀和剩余的尾部。
Iterator
的{{3}}方法在这里证明是有用的,因为它创建了一个由迭代器支持的序列。剩下的只是连接序列。
以下是您如何进行一项更改:
Iterator<T>
请注意,两个序列是从同一个迭代器创建的,但它可以,因为
val seq = (1..10).asSequence().constrainOnce()
val modified = seq.iterator().let { iter ->
iter.asSequence().take(5).map { it * -1 } + iter.asSequence()
}
被懒惰地评估以下是如何将其推广到任意数量的序列运算符:
Sequence
此fun <T> Sequence<T>.changePrefixes(vararg operators: Sequence<T>.() -> Sequence<T>)
: Sequence<T> {
val i = iterator()
return operators.fold(emptySequence<T>()) { acc, it -> acc + i.asSequence().it() } +
i.asSequence()
}
生成由fold
从迭代器operators
支持的序列提供的连锁序列链,然后将未修改的尾部附加到i
结果。
此实施的限制是,当运营商包含fold
时,被拒绝的项目将被删除,并且不会被发送到下一个序列。