У вас есть внутренняя проблема.Iterable
подразумевает, что вы можете получить несколько итераторов.Iterator
подразумевает, что вы можете пройти только один раз.Это означает, что ваш Iterable[Iterable[T]]
должен иметь возможность производить Iterator[Iterable[T]]
с.Но когда он возвращает элемент - Iterable[T]
- и запрашивает несколько итераторов, базовый отдельный итератор не может выполнить это без кэширования результатов списка (слишком большого) или , вызывающегоисходный, повторяемый и повторяющий абсолютно все снова (очень неэффективно).
Итак, хотя вы могли бы сделать это, я думаю, вы должны понимать свою проблему по-другому.
Если бы вместо этого вы могли начать с Seq
, вы могли бы получить подмножества в качестве диапазонов.
Если вы уже знаете, как хотите использовать итерацию, вы можете написать метод
def process[T](source: Iterable[T])(starts: T => Boolean)(handlers: T => Unit *)
, который увеличивается через набор обработчиков каждый раз, когда starts
запускает "true".Если есть какой-то способ, которым вы можете выполнить свою обработку за один раз, то вот как это сделать.(Однако вашим обработчикам придется сохранять состояние через изменяемые структуры данных или переменные.)
Если вы можете разрешить итерации во внешнем списке, чтобы разбить внутренний список, вы можете получить Iterable[Iterator[T]]
с дополнительным ограничениемчто после того, как вы перейдете к более позднему подитератору, все предыдущие подитераторы будут недействительными.
Вот решение последнего типа (от Iterator[T]
до Iterator[Iterator[T]]
; его можно обернуть всделать внешние слои Iterable
вместо).
class GroupedBy[T](source: Iterator[T])(starts: T => Boolean)
extends Iterator[Iterator[T]] {
private val underlying = source
private var saved: T = _
private var cached = false
private var starting = false
private def cacheNext() {
saved = underlying.next
starting = starts(saved)
cached = true
}
private def oops() { throw new java.util.NoSuchElementException("empty iterator") }
// Comment the next line if you do NOT want the first element to always start a group
if (underlying.hasNext) { cacheNext(); starting = true }
def hasNext = {
while (!(cached && starting) && underlying.hasNext) cacheNext()
cached && starting
}
def next = {
if (!(cached && starting) && !hasNext) oops()
starting = false
new Iterator[T] {
var presumablyMore = true
def hasNext = {
if (!cached && !starting && underlying.hasNext && presumablyMore) cacheNext()
presumablyMore = cached && !starting
presumablyMore
}
def next = {
if (presumablyMore && (cached || hasNext)) {
cached = false
saved
}
else oops()
}
}
}
}