来自C / C ++背景,我对编程的功能风格不是很熟悉所以我的所有代码都非常必要,因为在大多数情况下我只是看不到更好的方法这样做。
我只是想知道是否有办法让这个 Scala 代码块更多" 功能"?
var line:String = "";
var lines:String = "";
do {
line = reader.readLine();
lines += line;
} while (line != null)
答案 0 :(得分:27)
这个怎么样?
val lines = Iterator.continually(reader.readLine()).takeWhile(_ != null).mkString
答案 1 :(得分:13)
好吧,在Scala你可以说:
val lines = scala.io.Source.fromFile("file.txt").mkString
但这只是一个图书糖。有关其他可能性,请参阅Read entire file in Scala?。您实际要问的是如何将函数范例应用于此问题。这是一个提示:
Source.fromFile("file.txt").getLines().foreach {println}
你知道这背后的想法吗?文件中的foreach
行执行println
函数。 BTW不用担心,getLines()
返回迭代器,而不是整个文件。现在更严肃的事了:
lines filter {_.startsWith("ab")} map {_.toUpperCase} foreach {println}
看到这个想法?取lines
(它可以是数组,列表,集合,迭代器,可以过滤的任何内容,其中包含具有startsWith
方法的项目)和filter
仅采用以{开头的项目{1}}。现在,通过应用"ab"
方法获取每个项目map
。最后toUpperCase
生成项目foreach
。
最后一个想法:你不仅限于一种类型。例如,假设您有一个包含整数的文件,每行一个。如果你想阅读该文件,解析数字并总结,只需说:
print
答案 2 :(得分:1)
添加如何使用我投票使用的以前新的nio
文件来实现相同的效果,因为它有几个优点:
val path: Path = Paths.get("foo.txt")
val lines = Source.fromInputStream(Files.newInputStream(path)).getLines()
// Now we can iterate the file or do anything we wont, e.g. concatenate
val result = lines.mkString
答案 3 :(得分:0)
我发现Stream
是一个非常好的方法:它创建了一个可重新遍历(如果需要)的序列:
def loadLines(in: java.io.BufferedReader): Stream[String] = {
val line = in.readLine
if (line == null) Stream.Empty
else Stream.cons(line, loadLines(in))
}
每个Stream
元素都有一个值(在这种情况下为String
,line
),并调用一个函数(在此示例中为loadLines(in)
)下一个元素,懒洋洋地,按需。这样可以获得良好的内存使用情况,特别是对于大型数据集 - 在需要之前不会读取行,并且除非某些内容实际上仍然存在,否则不会保留行。然而,你也可以回到之前的Stream
元素并再次向前移动,产生完全相同的结果。