2 Stimmen

Scala : sauberste Weg, um rekursiv parsen Dateien Überprüfung auf mehrere Zeichenfolgen

Ich möchte ein Scala-Skript schreiben, um alle Dateien in einem Verzeichnis rekursiv zu verarbeiten. Für jede Datei möchte ich sehen, ob es Fälle gibt, in denen eine Zeichenkette in Zeile X und Zeile X - 2 vorkommt. Wenn ein solcher Fall auftritt, möchte ich die Verarbeitung dieser Datei stoppen und den Dateinamen zu einer Zuordnung von Dateinamen zu Vorkommenszahlen hinzufügen. Ich habe gerade angefangen, Scala heute zu lernen, ich habe die Datei recurse Code arbeiten, und brauchen etwas Hilfe mit der Zeichenkette suchen, hier ist, was ich so weit haben:

import java.io.File
import scala.io.Source

val s1= "CmdNum = 506"
val s2 = "Data = [0000,]"

def processFile(f: File) {
  val lines = scala.io.Source.fromFile(f).getLines.toArray
  for (i = 0 to lines.length - 1) {
    // want to do string searches here, see if line contains s1 and line two lines above also contains s1
    //println(lines(i))
  }
}

def recursiveListFiles(f: File): Array[File] = {
  val these = f.listFiles
  if (these != null) {
    for (i = 0 to these.length - 1) {
      if (these(i).isFile) {
        processFile(these(i))
      }
    }
    these ++ these.filter(_.isDirectory).flatMap(recursiveListFiles)
  }
  else {
    Array[File]()
  }
}

println(recursiveListFiles(new File(args(0))))

7voto

huynhjl Punkte 41112

Sie können so vorgehen:

def processFile(f: File) {
  val src = Source.fromFile(f)
  val hit = src.getLines().sliding(3).exists{ 
    case List(l0, l1, l2) => l0.contains(s1) && l2.contains(s1)
    case _ => false
  }
  src.close
  // do something depending on hit like adding to a Map
}

Erstens müssen Sie nicht in ein Array konvertieren, sondern können den Iterator beibehalten, um nur die Zeilen zu lesen, die für die Suche nach einer Übereinstimmung erforderlich sind.

Sie können verwenden sliding um einen abgeleiteten Iterator zu erhalten, der ein gleitendes Fenster von 3 Zeilen verwendet, in dem Sie nach der Zeichenkette in der Zeile i y i+2 .

exists prüft, ob ein Element dieses gleitenden Iterators ein Prädikat erfüllt. Die case wird der Einfachheit halber die 3 Zeilen des Schiebefensterelements in 3 Vals aufteilen. Ich musste die REPL verwenden, um herauszufinden, welchen Typ das Sliding wirklich zurückgibt .

Vergessen Sie schließlich nicht, src zu schließen.

Wenn Sie die Anzahl der Vorkommnisse benötigen:

  val count = src.getLines().sliding(3).filter{ 
    case List(l0, l1, l2) => l0.contains(s1) && l2.contains(s1)
    case _ => false
  }.size

Sie filtern die Vorkommen und erhalten dann die Größe...

bearbeitet für Match-Fehler bei Dateien kürzer als 3 Zeilen

2voto

Daniel C. Sobral Punkte 290004

Hier ist eine alternative Möglichkeit, dies zu tun:

import java.io.File
import scala.io.Source

val s1= "CmdNum = 506"

def filesAt(f: File): Array[File] = if (f.isDirectory) f.listFiles flatMap filesAt else Array(f)

def filterFiles(arr: Array[File]) = arr filter (
    Source
    fromFile _
    getLines ()
    sliding 3
    exists { 
        case List(l1, l2, l3) => List(l1, l3) forall (_ contains s1)
        case _ => false
    }
)

println(filterFiles(filesAt(new File(args(0)))))

Allerdings muss ich zugeben, dass ich ein bisschen geschummelt habe. Ich musste das eigentlich schreiben, anstatt Source fromFile _ :

Source.fromFile(_)(scala.io.Codec.ISO8859)

Denn sonst würde Scala bei ungültigen UTF-8-Kodierungen kotzen.

1voto

Kevin Wright Punkte 49145

Es muss verfeinert werden, um mit Dateien, die kürzer als 3 Zeilen sind, umgehen zu können, aber für einen ersten Versuch würde ich so etwas versuchen:

def checkFile(file: File) = {
  val lines = ...
  (lines zip lines.tail.tail) exists { _1 = _2 }
}

Dann

val files = ...
val validFiles = files filter { checkFile }

Entschuldigen Sie, dass ich mich so kurz fasse, ich antworte von meinem Handy aus...

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X