2017-01-05 52 views
0

我有一個簡單的文件系統抽象:如何使用Stream遍歷Scala中的樹?

trait PathItem { val label: String } 

case class PathEnd(label: String, uri: String) extends PathItem 

case class PathDirectory(
    label: String = "", 
    contents: List[PathItem] = List.empty[PathItem] 
) extends PathItem 

採用這種結構,我可以建立子目錄(PathDirectory)和文件(PATHEND)的任意複雜的樹。

我怎麼能使用Scala的流以提取的「文件」列表是這樣的:

getFileStream(rootDir).foreach(f => println(f.uri)) 
getFileStream(rootDir).find(_.uri == "someTargetURI") 

// where getFileStream creates a Stream[PathEnd] given a starting rootDir 

通過樹這樣的傳球是有點酷,但我不理解如何創建來自scaladoc的Stream。

(我知道我可以只寫一個簡單的遞歸函數,但我想在這裏神交流。)

+0

你幾乎可以治療'Stream'(或'Iterator'),你會一個'List',以及隨後的元素將被懶洋洋地計算相同。編輯:一個很好的入門書:http://alvinalexander.com/scala/how-to-use-stream-class-lazy-list-scala-cookbook – spiffman

回答

1

正如評論所說,你基本上可以治療Stream一樣你將一個List和你會得到期望的懶惰評估序列。您的解決方案:

def fileStream(p: PathItem): Stream[PathEnd] = { 
    p match { 
     case pe: PathEnd => Stream(pe) 
     case pd: PathDirectory => pd.contents.toStream.flatMap(fileStream) 
    } 
} 

注意flatMap以避免造成StreamStream實例。

測試:

scala> val pd = PathDirectory(root,List(
    PathDirectory("src",List(PathDirectory("main",List(PathEnd("file.scala","file.uri"))))), 
    PathDirectory("test",List(PathDirectory("main",List(PathEnd("test.scala","test.uri"))))))) 
scala> fileStream(pd).foreach(println) 

PathEnd(file.scala,file.uri) 
PathEnd(test.scala,test.uri)