Как скопировать итератор в Scala? - PullRequest
15 голосов
/ 17 октября 2011

О дубликате

Это НЕ дубликат Как клонировать итератор?

Пожалуйста, не закрывайте этот вопрос вслепую, всеответы в так называемом дубликате НЕ работают.ОП отвечает за другую проблему, и, очевидно, ответы соответствуют проблеме ЕГО, но не моей.

Не каждый подобный вопрос является дубликатом, на SE есть такая особенность, как «вопрос расширения»,Единственный способ - снова спросить на ту же тему, чтобы получить разные, рабочие ответы.

Задача

У меня есть итератор.Я хотел бы получить его копию (дубликат), чтобы затем я мог продолжить работу с оригиналом и копировать совершенно независимо.

Важно

Копирование с помощью отражения или сериализации отсутствует-go (снижение производительности).

Пример

var list = List(1,2,3,4,5)
var it1 = list.iterator
it1.next()

var it2 = it1   // (*)
it2.next()

println(it1.next())

Это просто ссылается на it1 , поэтому при изменении it1, it2 также изменяется и наоборот.

В приведенном выше примере используется List , в настоящее время я борюсь с HashMap , но вопрос общий - просто итератор.

Подход № 1

Если вы редактируете строку (*) и пишете:

var it2 = it1.toList.iterator

(это было предложено в качестве решения в связанном вопросе) исключение выдается при выполнении программы.

Подход # 2

"Вы берете список и ...".Нет не знаюУ меня нет списка, у меня есть итератор.В общем, я ничего не знаю о коллекции, которая лежит в основе итератора, единственное, что у меня есть, это итератор.Я должен "раскошелиться".

Ответы [ 3 ]

14 голосов
/ 17 октября 2011

Вы не можете продублировать итератор, не уничтожив его. Контракт на iterator заключается в том, что его можно пройти только один раз.

Вопрос, с которым вы связались, показывает, как получить две копии в обмен на ту, которую вы уничтожили. Вы не можете продолжать использовать оригинал, но теперь вы можете запустить две новые копии независимо друг от друга.

9 голосов
/ 18 октября 2011

Довольно просто создать итератор List, который можно дублировать, не разрушая его: это, в основном, определение метода iterator, скопированного из источника List с добавленным методом fork:

class ForkableIterator[A] (list: List[A]) extends Iterator[A] {
    var these = list
    def hasNext: Boolean = !these.isEmpty
    def next: A = 
      if (hasNext) {
        val result = these.head; these = these.tail; result
      } else Iterator.empty.next
    def fork = new ForkableIterator(these)
}

Использование:

scala> val it = new ForkableIterator(List(1,2,3,4,5,6))
it: ForkableIterator[Int] = non-empty iterator

scala> it.next
res72: Int = 1

scala> val it2 = it.fork
it2: ForkableIterator[Int] = non-empty iterator

scala> it2.next
res73: Int = 2

scala> it2.next
res74: Int = 3

scala> it.next
res75: Int = 2

Я посмотрел, как это сделать для HashMap, но это кажется более сложным (отчасти потому, что существуют разные реализации карт в зависимости от размера коллекции).Поэтому, вероятно, лучше всего использовать приведенную выше реализацию на yourMap.toList.

6 голосов
/ 18 октября 2011

Как сказал Рекс, невозможно сделать копию Итератора, не уничтожив ее.Тем не менее, в чем проблема с duplicate?

var list = List(1,2,3,4,5)
var it1 = list.iterator
it1.next()

val (it1a, it1b) = it1.duplicate
it1 = it1a
var it2 = it1b
it2.next()

println(it1.next())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...