3

我是一个新手,试图读取一个文件并创建一个 Vector[Vector[Char]]。文件的每一行都应该产生一个不同的向量。

这是我想出的:

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) (_ +: _)

该文件永远不会很大,因此可伸缩性不是问题。上面的代码似乎可以工作,但我觉得它在谷仓里到处都是。有没有更简单、更直接的方法来做到这一点?

4

4 回答 4

5

以下是使用 Scala 2.10 的解决方案:

source.getLines.to[Vector].map(_.to[Vector])
于 2012-11-10T16:54:50.260 回答
1

正如我在上面的评论中指出的那样,IndexedSeq在您需要能够在恒定时间内抓取特定索引处的元素的情况下使用它更为惯用。当前的默认实现IndexedSeqVector,因此如果您编写以下内容:

val xs = IndexedSeq(1, 2, 3)

您实际上会Vector[Int]在幕后得到 a ,但这只是一个实现细节,因为它是静态类型为IndexedSeq[Int]. 如果将来引入新的、性能更高的默认实现,您将免费从更改中受益。

UsingIndexedSeq还允许您非常简洁地编写此操作,而无需依赖 Scala 2.10 的新to方法。假设我们有一个s我们正在其他地方打开和关闭的来源,这就是您所需要的:

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

WherewrapString是一种scala.Predef支持将字符串视为字符序列的方法。

于 2012-11-10T18:02:14.920 回答
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]

(首先在迭代器上映射,这样您就不必创建两次向量。)

于 2012-11-10T18:16:38.227 回答
0

一点改进,避免foldLeft()

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

但是请记住,您实际上必须关闭Source.fromFile("test.txt")对象。

于 2012-11-10T16:52:18.747 回答