2

Programming in Scala book を使用して Scala を学習しようとすると、ファイルから行を読み取るための非常に基本的な例があります。私はそれを拡張してファイルを1行ずつ読み取り、特定のフレーズを探し、その行が見つかった場合はその行に続く次の6行を出力しようとしています。Java や Perl などで簡単にスクリプトを作成できますが、Scala でそれを行う方法がわかりません (おそらく、言語にまだ慣れていないためです...)

以下は、Programming in Scala book の一部を改変したサンプル コードです。

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

for式を次のようなものに置き換えることができます。

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

スライドの仕組みが原因で、最後の6行にある場合、これは秘密のフレーズを見逃すことに注意してください(リストの最後に最初に遭遇したときに停止します)。

これはさまざまな方法で回避できますが、最も簡単な方法は、処理する前に6つのダミー行をリストに追加することです。

于 2012-11-30T23:36:07.453 に答える
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 に答える
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 に答える