在Scala中表示readline循环的最佳方法?

时间:2011-08-13 18:26:36

标签: scala functional-programming

来自C / C ++背景,我对编程的功能风格不是很熟悉所以我的所有代码都非常必要,因为在大多数情况下我只是看不到更好的方法这样做。

我只是想知道是否有办法让这个 Scala 代码块更多" 功能"?

var line:String = "";
var lines:String = "";

do {
    line = reader.readLine();
    lines += line;
} while (line != null)

4 个答案:

答案 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元素都有一个值(在这种情况下为Stringline),并调用一个函数(在此示例中为loadLines(in))下一个元素,懒洋洋地,按需。这样可以获得良好的内存使用情况,特别是对于大型数据集 - 在需要之前不会读取行,并且除非某些内容实际上仍然存在,否则不会保留行。然而,你也可以回到之前的Stream元素并再次向前移动,产生完全相同的结果。