2012-11-10 124 views
3

我是一個新手,試圖讀取文件並創建一個矢量[矢量[字符]]。文件的每一行應該導致不同的向量。從文件創建一個矢量[矢量[字符]]

下面是我想出:

val empty: Vector[Vector[Char]]  = Vector() 
lazy val lines: List[String]   = Source.fromFile("test.txt").getLines.toList 
lazy val vecList: List[Vector[Char]] = lines.map(str => Vector(str: _*)) 
lazy val vector: Vector[Vector[Char]] = vecList.foldRight(empty) (_ +: _) 

該文件將永遠不會很大,所以可擴展性不是問題。上面的代碼似乎有效,但我覺得它在穀倉周圍。有沒有更簡單,更直接的方法來做到這一點?

+1

作爲一個方面說明:是否有一個特殊的原因,你需要一個'Vector'?在Scala中,只有指定具有您需要的性能特徵的集合類型才更爲習慣 - 即,在這種情況下可能是'IndexedSeq' - 而不是實現。 –

+0

@ Travis。我剛剛完成了Martin Odersky在Scala的Coursera課程,我正在嘗試擴展其中一項任務。該任務使用了Vector,所以我堅持使用它。不幸的是,該課程沒有文件I/O,所以我也試圖學習一些。 – saulspatz

+0

謝謝大家誰回答。這些都比我想出來的更加簡潔。這會讓我花一點時間來圍繞他們中的一些人。我還沒有安裝Scala 2.10,但這個「to」方法看起來非常有吸引力。 – saulspatz

回答

0

稍加改進,避免foldLeft()

Vector(Source.fromFile("test.txt").getLines.toSeq: _*) map {l => Vector(l: _*)} 

但是記住你確實有收Source.fromFile("test.txt")對象。

5

下面是使用Scala的2.10解決方案:

source.getLines.to[Vector].map(_.to[Vector]) 
1

正如我在上面評論指出,這是更地道使用IndexedSeq的情況下,您需要能夠在一個特定的指數,抓起一個元素在不斷的時間。的IndexedSeq當前默認的實現是Vector,所以如果你寫:

val xs = IndexedSeq(1, 2, 3) 

你就會得到一個幕後Vector[Int],但是這只是一個實現細節,因爲它是靜態類型爲IndexedSeq[Int]。如果將來推出一個新的,性能更高的默認實現,您將從免費更改中受益。

使用IndexedSeq還允許您在不依賴Scala 2.10的新to方法的情況下非常簡潔地編寫此操作。假設我們有一個源s,我們正在打開和關閉其他地方,這是所有你需要:

val lines: IndexedSeq[IndexedSeq[Char]] = s.getLines.map(wrapString).toIndexedSeq 

wrapStringscala.Predef提供了一種方法來支持處理字符串作爲字符序列。

1
import scala.io.Source 

2.9或更早版本:

Vector() ++ Source.fromFile("test.txt").getLines.map(Vector() ++ _) 

2.10後:

Source.fromFile("test.txt").getLines.map(_.to[Vector]).to[Vector] 

(地圖上的第一個迭代器,這樣你就不必重複建立向量)