2

尝试使用 Programming in Scala 这本书来学习 Scala,他们有一个非常基本的示例来从文件中读取行。我正在尝试对其进行扩展并逐行读取文件,查找某个短语,然后在找到该行后打印该行之后的接下来的 6 行。我可以用 java 或 Perl 之类的语言轻松编写脚本,但我不知道如何在 Scala 中编写脚本(可能是因为我还不太熟悉该语言......)

这是《Scala 编程》一书中的半改编示例代码,

import scala.io.Source

if(args.length>0) {
    val lines = Source.fromFile(args(0)).getLines().toList
        for(line<-lines) {
            if(line.contains("secretPhrase")) {
                println(line)
                        //How to get the next lines here?   
            }
        }
}
else
Console.err.println("Pleaseenterfilename")
4

4 回答 4

7

你可以像在java中那样做

if(args.length > 0) {
  val lines = Source.fromFile(args(0)).getLines.toList
  for(i <- 0 until lines.size) {
    if(lines(i).contains("secretPhrase")) {
      for(j <- i+1 to i+6) println(lines(j))
    }
  }
}

或者你使用 scala 成语让它更短

if(args.length > 0) {
  val lines = Source.fromFile(args(0)).getLines
  lines.dropWhile(!_.contains("secretPhrase"))
       .drop(1).take(6).foreach(println)
}
于 2012-11-30T23:40:08.287 回答
2

视图是使迭代列表在 Scala 中高效的秘诀。尝试这个:

val l = Source.fromFile(args(0)).getLines().toList

l.view.zipWithIndex.filter(_._1.contains("secretPhrase")).foreach { 
  case (s, i) => l.view(i+1, i+7).foreach(println(_))
}
于 2012-12-02T23:02:00.697 回答
2

您可以将 for 表达式替换为以下内容:

lines.sliding(7).filter(l => l(0).contains("secretPhrase")).foreach(println)

请注意,如果它在最后 6 行中,由于滑动的工作方式,这将错过秘密短语(它在第一次遇到列表末尾时停止)。

您可以通过多种方式解决此问题,最简单的可能是在处理之前将六个虚拟行附加到列表中。

于 2012-11-30T23:36:07.453 回答
1

for在集合上使用仅引用该元素,这就是为什么您不能引用以下行的原因。如果您需要引用集合本身,有几种方法:

1)使用内置方法。合适的是tails. 例如,如果我们的集合是List("a","b","c")

scala> List("a","b","c").tails foreach println
List(a, b, c)
List(b, c)
List(c)
List()

这几乎是我们需要的,除了我们不想List()在最后检查空,所以我们可以 a) 检查列表是否为空:

lines.tails foreach { xs => 
  if (!xs.isEmpty && (xs.head contains "secretPhrase")) 
    xs take 6 foreach println
}

或 b) 用于init获取除最后一个以外的所有元素:

lines.tails.toList.init foreach { xs => 
  if (xs.head contains "secretPhrase") 
    xs take 6 foreach println
}

2)while循环/递归

a)while循环:

var xs = lines
while (!xs.isEmpty) {
  if (xs.head contains "secretPhrase") 
    xs take 6 foreach println
  xs = xs.tail
}

b) 等价递归

def print6(xs: List[String]): Unit = if (!xs.isEmpty) {
  if (xs.head contains "secretPhrase")
    xs take 6 foreach println
  print6(xs.tail)
}

print6(lines)
于 2012-12-01T22:17:33.413 回答