我試圖重構一個當前使用相當昂貴的遞歸算法生成Seq[X]
的組件,以便生成Stream[X]
,因此可以按需加載/計算X
,並且生產者不必嘗試事先猜測爲了滿足消費者需要做多少挖掘。玫瑰樹的懶惰,廣度優先遍歷?
從我讀過的內容來看,這是「展開」的理想用途,所以這就是我一直試圖採用的路線。
這是我的unfold
功能,從David Pollak's example衍生,已審覈通過一定的莫里斯先生:
def unfold[T,R](init: T)(f: T => Option[(R,T)]): Stream[R] = f(init) match {
case None => Stream[R]()
case Some((r,v)) => r #:: unfold(v)(f)
}
而且這裏有一個小的樹試試我們的運氣:
case class Node[A](data: A, children: List[Node[A]]) {
override def toString = "Node(" + data + ", children=(" +
children.map(_.data).mkString(",") +
"))"
}
val tree = Node("root", List(
Node("/a", List(
Node("https://stackoverflow.com/a/1", Nil),
Node("https://stackoverflow.com/a/2", Nil)
)),
Node("/b", List(
Node("/b/1", List(
Node("/b/1/x", Nil),
Node("/b/1/y", Nil)
)),
Node("/b/2", List(
Node("/b/2/x", Nil),
Node("/b/2/y", Nil),
Node("/b/2/z", Nil)
))
))
))
而且最後,這是我在廣度優先的遍歷中使用展開的失敗嘗試:
val initial = List(tree)
val traversed = ScalaUtils.unfold(initial) {
case node :: Nil =>
Some((node, node.children))
case node :: nodes =>
Some((node, nodes))
case x =>
None
}
assertEquals(12, traversed.size) // Fails, 8 elements found
/*
traversed foreach println =>
Node(root, children=(/a,/b))
Node(/a, children=(/a/1,/a/2))
Node(/b, children=(/b/1,/b/2))
Node(/b/1, children=(/b/1/x,/b/1/y))
Node(/b/2, children=(/b/2/x,/b/2/y,/b/2/z))
Node(/b/2/x, children=())
Node(/b/2/y, children=())
Node(/b/2/z, children=())
*/
任何人都可以給我一些關於如何修復(或重寫)我的遍歷邏輯的提示,以便返回所有節點?謝謝!
男人,我覺得啞巴。謝謝!! – 2011-04-30 00:23:04