2016-08-24 127 views
1

我寫了下面的代碼,期待最後的print方法顯示兩個迭代器組合的元素。相反,它只顯示perfectSquares的元素。誰可以給我解釋一下這個?交錯迭代器

object Fuge { 

    def main(args: Array[String]) : Unit = { 

    perfectSquares.takeWhile(_ < 100).foreach(square => print(square + " ")) 
    println() 
    triangles.takeWhile(_ < 100).foreach(triangle => print(triangle + " ")) 
    println() 
    (perfectSquares++triangles).takeWhile(_ < 100).foreach(combine => print(combine + " ")) 

    } 

    def perfectSquares : Iterator[Int] = { 
    Iterator.from(1).map(x => x * x) 
    } 

    def triangles : Iterator[Int] = { 
    Iterator.from(1).map(n => (n * (n + 1)/2)) 
    } 

} 

輸出

1 4 9 16 25 36 49 64 81  
1 3 6 10 15 21 28 36 45 55 66 78 91 
1 4 9 16 25 36 49 64 81 
+1

'takeWhile' *停止*當它擊中的東西,不滿足謂詞。 – user2357112

回答

2

從文檔上takeWhile

/** Takes longest prefix of values produced by this iterator that satisfy a predicate. 
    * 
    * @param p The predicate used to test elements. 
    * @return An iterator returning the values produced by this iterator, until 
    *   this iterator produces a value that does not satisfy 
    *   the predicate `p`. 
    * @note Reuse: $consumesAndProducesIterator 
    */ 

這意味着迭代器停止在該關口。你創建的是一個迭代器,它遠遠超過了100,然後在某個時刻再次從1開始。但takeWhile不會走那麼遠,因爲它已經碰到了一些高於100參見:

object Fuge { 
    def main(args: Array[String]) : Unit = { 

    perfectSquares.takeWhile(_ < 100).foreach(square => print(square + " ")) 
    println() 
    triangles.takeWhile(_ < 100).foreach(triangle => print(triangle + " ")) 
    println() 
    def interleave (a: Iterator[Int], b: Iterator[Int]): Stream[Int] = { 
     if (a.isEmpty || b.isEmpty) { Stream.empty } 
     else { 
     a.next() #:: b.next() #:: interleave(a, b) 
     } 
    } 
    lazy val interleaved = interleave(perfectSquares, triangles) 
    interleaved.takeWhile(_ < 100).foreach(combine => print(combine + " ")) 
    } 

    def perfectSquares : Iterator[Int] = { 
    Iterator.from(1).map(x => x * x) 
    } 

    def triangles : Iterator[Int] = { 
    Iterator.from(1).map(n => (n * (n + 1)/2)) 
    } 
} 

這裏我使用的是流延遲計算整數序列。這樣我們可以確保交織。請注意,這只是交錯式的,沒有排序。

這產生了:

1 4 9 16 25 36 49 64 81 
1 3 6 10 15 21 28 36 45 55 66 78 91 
1 1 4 3 9 6 16 10 25 15 36 21 49 28 64 36 81 45 

到流期間的排序,你需要一個BufferedIterator,並改變了interleave功能位。這是因爲調用next()可以提升迭代器 - 你不能回頭。而你無法知道你需要從列表a需要多少項目,然後你需要從列表b的項目,反之亦然。但是BufferedIterator可以讓你打電話head,這是一個'偷看',並沒有推進迭代器。現在的代碼變成:

object Fuge { 
    def main(args: Array[String]) : Unit = { 
    perfectSquares.takeWhile(_ < 100).foreach(square => print(square + " ")) 
    println() 
    triangles.takeWhile(_ < 100).foreach(triangle => print(triangle + " ")) 
    println() 
    def interleave (a: BufferedIterator[Int], b: BufferedIterator[Int]): Stream[Int] = { 
     if (a.isEmpty || b.isEmpty) { Stream.empty } 
     else if (a.head <= b.head){ 
     a.next() #:: interleave(a, b) 
     } else { 
     b.next() #:: interleave(a, b) 
     } 
    } 
    lazy val interleaved = interleave(perfectSquares.buffered, triangles.buffered) 
    interleaved.takeWhile(_ < 100).foreach(combine => print(combine + " ")) 
    } 

    def perfectSquares : Iterator[Int] = { 
    Iterator.from(1).map(x => x * x) 
    } 

    def triangles : Iterator[Int] = { 
    Iterator.from(1).map(n => (n * (n + 1)/2)) 
    } 
} 

,輸出是:

1 4 9 16 25 36 49 64 81 
1 3 6 10 15 21 28 36 45 55 66 78 91 
1 1 3 4 6 9 10 15 16 21 25 28 36 36 45 49 55 64 66 78 81 91 
+0

感謝您的澄清。你如何交織迭代器中的值,以便不需要單獨的takeWhile?我希望迭代器中的值爲:1,1,3,4,6,9 - 我想我會排序? –

+0

如果您希望輸出進行交錯排序,然後對這兩組進行排序併合並。類似Merge-Sort的「合併」例程。 – Jegan

+0

@AmirAfghani查看我的更新。 –