2011-10-17 39 views
13

关于重复

这不是How to clone an iterator?如何在Scala中复制迭代器?

重复请不要盲目关闭这个问题,给出所有的答案所谓重复切勿工作。 OP负责另一个问题,显然,答案符合他的问题,但不是我的。

并非每一个类似的问题都是重复的,SE上有“扩展问题”这样的功能,唯一的办法就是再次询问同一主题以获得不同的工作答案。

问题

我有迭代器。我想获得它的副本(复制),那么我可以完全独立地进行原创和复制。

重要

复制通过反射或序列号为NO-GO(性能损失)。

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

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

println(it1.next()) 

改变IT1IT2当变化以及反之亦然这将使简单地参照IT1,所以。

上面的例子使用列表,我目前正在与HashMap的挣扎,但问题是一般人 - 只要迭代器。

方法#1

如果您编辑行(*),并写:

var it2 = it1.toList.iterator 

(这个建议作为链接的问题的解决方案),而执行程序的异常被抛出。

方法2

“你拿的名单和...”。不,我不知道。我没有列表,我有迭代器。一般来说,我不知道任何关于迭代器的基础,我唯一拥有的就是迭代器。我必须“分岔”它。

+0

这是重复的。用我的答案解决另一个问题;它适用于所有情况。 (该方法也称为“重复”。) –

+0

我已在另一页上编辑Miles的回答,以突出显示您在此处尝试执行的操作不起作用,并提供可行的解决方案。 –

+2

@克雷克尔,不,它不是通过答案来判断的。在其他问题中给出的答案回答了OTHER问题,它们不适合我的问题。我很感谢你的回答,他们很有教育意义,我确信我知道更多,但他们不能解决这个问题。 – greenoldman

回答

14

您不能复制迭代器而不销毁迭代器。 iterator的合同是它只能被遍历一次。

您链接的问题显示如何获得两份副本以换取您销毁的一份。您无法继续使用原件,但现在可以单独向前运行两个新副本。

+0

是否有保证(通过语言)这将适用于任何集合的迭代器?然而,采用这种方法,无论如何我会遇到问题 - 例如,我有两个循环,并且我必须在嵌套循环的下一个点开始,当主迭代器是时,但我不能销毁它。 – greenoldman

+1

它保证适用于任何迭代器。重构你的外层循环来更新它的迭代器。或者,将您的迭代器转换为流并使用流来完成所有任务。 –

8

这是很容易地创建一个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上使用上面的实现。

+1

很有教育意义,谢谢。 – greenoldman

+0

@macias这不仅仅是教育。我做了一个基准测试,发现这比使用'duplicate'快12倍**,比'toList'快29%,然后在该列表上创建2个新迭代器。总之,不要在性能重要的地方使用“重复”。 (29%的数字将低估'For​​kableIterator'的实际速度提升,因为基准测试不会单独测量迭代器的复制。) –

+1

迭代器的含义,我如何理解它,是根据需求遍历数据。例如,当我们从文件中读取数据时。像:val iterator:Iterator [String] = scala.io.Source.fromFile(fileName).getLines()。但是在这个例子中/ asnwer,我们通过已经填充的List(可能消耗大量内存)来提供这个迭代器。这不是我(我)可能想从迭代器中获得的。然后更好地使用List本身。 – ses

5

正如雷克斯所说,不可能在不破坏迭代器的情况下复制一个迭代器。这就是说,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()) 
+1

一个问题可能是,如果你复制每一个循环,这是低效的;你最终会得到一个你不能扔掉的巨大垃圾链。 –

+0

啊,丹尼尔,你已经用** duplicate ** :-)发布了问题列表。 – greenoldman

+0

我觉得笨拙的“重复”成语。我可以相当想象,相反,像'val it2 = it1.clone' – matanster