2013-05-05 97 views
0

我有一個Scala Iterator(我可以使用任何數據類型舒適爲我的目的),我從Seq施放。我想保留它,直到我準備好了,但我還希望能夠在O(1)中獲得它的大小。我想知道是否有內置的方式來設置,這將允許我在迭代對象上保持迭代器的大小。Scala迭代器/流與已知大小

+1

爲什麼你需要傳遞迭代器而不是原來的'Seq'?順便寫下* cast * ...你不能從'Seq'投到'Iterator',所以我假設你的意思是'seq.iterator'。在我看來,操縱迭代器但需要知道大小是有風險的。只要有訪問迭代器的方法調用'next()'就會改變迭代器的大小... – huynhjl 2013-05-05 21:47:00

+0

如果你生產一堆數據並打算把它扔進一個'數組'。通常的'Iterator'->'Array'通路必須使用可增長的數組,如果您擁有大量數據,它可以很好地漸進式地生成垃圾數量,但如果您事先知道大小,則可能會產生大量垃圾。 – 2013-05-06 14:08:28

回答

1

最好的辦法是把它包裝在另一個迭代器中,如果你可以支付額外的間接成本。

class SizedIterator[A](underlying: Iterator[A], val initalSize: Int) extends Iterator[A] { 
    def next = underlying.next 
    def hasNext = underlying.hasNext 
} 

然後

new SizedIterator(mySeq.iterator, mySeq.length) 

請記住,但是,如果你映射或任何新的SizedIterator你會最終有一個樸素Iterator,不再知道initialSize多久。

另外請記住,你不知道迭代器消耗了多少,所以initialSize是大小的上限,但是當你使用它時可能沒有剩餘。

或者,可以

mySeq.iterator.zipWithIndex.map{ case (x,i) => (x, mySeq.length-1) }.take(mySeq.length) 

以產生Iterator即對所述元件和左元素(包括一個 - you'll從不打零這樣)的數目。

如果你只是想用一個已知的大小,將告訴你在O(1),上投SeqIterable.length方法會以最快的速度解決事情的方法將有當它是一個Seq - 這是整點的重寫方法 - 因此不會(通常)每次消耗新的Iterator。但這需要你保持Iterable左右,而不僅僅是Iterator

+0

@ alex23 - 你對迭代器做的任何事情都可能會消耗掉所有的東西(除了'hasNext','next'將只消耗一個元素)。你可以找到大小,但是沒有什麼可以留下(一般來說 - 它甚至不承諾,但它不承諾_not_不使用它,而這是實現大小的最簡單方法)。你唯一的希望是調用自己返回一個你想要的迭代器的方法(它可能只是具有更新狀態的迭代器,但這取決於實現的決定),直到你最後一次調用(產生任何東西,如只要你以你想要的結束就行)。 – 2013-05-05 22:38:35

+0

我不相信你的'SizedIterator'增加了任何超過普通對'(Iterator [T],Int)'的東西'......你能說服我嗎? – 2013-05-06 09:16:47

+0

@MilesSabin - 它不提供太多。它保留'Iterator [T]'接口,以便您可以在需要'Iterator [T]'的任何位置傳遞它,並將模式再次返回以恢復長度,但這在嘗試編寫健壯的代碼時通常不可取。我將它作爲所要求的最接近的解決方案。我不確定要求別的東西不會更好! – 2013-05-06 10:48:05