Я думаю о чем-то с сигнатурой типа fun <T> Sequence<T>.destruct(): Pair<T, Sequence<T>>?
, которая вернет null
для пустой последовательности, иначе пара первого и остального приемника.
Я считаю, что ответ "нет". На этой странице перечислены все стандартные Sequence
функции, а поиск по слову «пара» не дает ничего, что соответствовало бы тому, что вы хотите.
Тем не менее, есть стандартная функция firstOrNull()
, а также функция drop()
, так что вы можете довольно легко написать свою собственную:
fun <T> Sequence<T>.destruct() =
firstOrNull()?.let { it to drop(1) }
Если вы работаете с последовательностями, которые можно использовать только один раз, описанное выше не сработает (поскольку и firstOrNull()
, и (в конечном итоге) DropSequence
вызовут метод получателя iterator()
). Вы можете обойти это, следуя той же общей идее, но более точно указав, как называется iterator()
:
fun <T> Sequence<T>.destruct(): Pair<T, Sequence<T>>? {
val iterator = iterator()
return if (iterator.hasNext()) {
iterator.next() to iterator.asSequence()
} else {
null
}
}
drop
не является терминалом: kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/drop.htmlХм, это не так. Я полагаю, проблема в том, что firstOrNull использовал его один раз, а затем тот, кто использует результат, попытается использовать его снова.
@DuncanMcGregor, честный вопрос: как вы ожидаете получить доступ к первому элементу последовательности, не вызывая итератор этой последовательности?
Возможно, вы могли бы создать свою собственную реализацию IteratorSequence
, в которой вы передаете Iterator
напрямую, чтобы метод iterator()
базовой последовательности не вызывался более одного раза. Затем вы можете создать пару из iterator.next()
и IteratorSequence(iterator)
.
Я думаю, вы сами ответили на свой вопрос ;-) Играя с этим решением, вам не нужно IteratorSequence
- iterator.asSequence()
или Sequence { iterator }
добьются цели.
Я думаю, что это будет потреблять последовательность дважды, так как
firstOrNull
иdrop
оба терминала