Sie bauen offensichtlich etwas, also möchten Sie vielleicht versuchen ... einen Baumeister!
Wie Jürgen, war mein erster Gedanke zu folden, wo Sie ein Ergebnis ansammeln.
Ein mutable.Builder führt die Akkumulation mit einem collection.generic.CanBuildFrom durch, um den Builder anzugeben, der zum Erstellen einer Zielsammlung aus einer Quellensammlung verwendet werden soll. Du hältst das veränderbare Ding gerade lange genug, um ein Ergebnis zu erhalten. Das ist also mein Plug für lokalisierte Veränderlichkeit. Angenommen, der Pfad von List [String] zu List [Project] ist unveränderlich.
Zu den anderen feinen Antworten (die mit nicht negativen Wertschätzungen), würde ich hinzufügen, dass funktionale Stil bedeutet funktionale Dekomposition, und in der Regel kleine Funktionen.
Wenn Sie keine Regex-Parser verwenden, vernachlässigen Sie keine Regexes in Ihren Musterübereinstimmungen.
Und versuchen Sie, die Punkte zu verschonen. Tatsächlich glaube ich, dass morgen ein Spare-the-Dots-Tag ist, und Leuten, die auf Punkte empfindlich reagieren, wird geraten, im Haus zu bleiben.
case class Project(user: String, name: String, description: String)
trait Sample {
val sample = """
|User=Hans
|Project=Blow up the moon
|The slugs are going to eat the mustard. // multiline possible!
|They are sneaky bastards, those slugs.
|
|User=Bob
|I haven't thought up a project name yet.
|
|User=Greta
|Project=Burn the witch
|It's necessary to escape from the witch before
|we blow up the moon. I hope Hans sees it my way.
|Once we burn the bitch, I mean witch, we can
|wreak whatever havoc pleases us.
|""".stripMargin
}
object Test extends App with Sample {
val kv = "(.*?)=(.*)".r
def nonnully(s: String) = if (s == null) "" else s + " "
val empty = Project(null, null, null)
val (res, dummy) = ((List.empty[Project], empty) /: sample.lines) { (acc, line) =>
val (sofar, cur) = acc
line match {
case kv("User", u) => (sofar, cur copy (user = u))
case kv("Project", n) => (sofar, cur copy (name = n))
case kv(k, _) => sys error s"Bad keyword $k"
case x if x.nonEmpty => (sofar, cur copy (description = s"${nonnully(cur.description)}$x"))
case _ if cur != empty => (cur :: sofar, empty)
case _ => (sofar, empty)
}
}
val ps = if (dummy == empty) res.reverse else (dummy :: res).reverse
Console println ps
}
Das Spiel kann auf diese Weise gestampft werden, auch:
val (res, dummy) = ((List.empty[Project], empty) /: sample.lines) {
case ((sofar, cur), kv("User", u)) => (sofar, cur copy (user = u))
case ((sofar, cur), kv("Project", n)) => (sofar, cur copy (name = n))
case ((sofar, cur), kv(k, _)) => sys error s"Bad keyword $k"
case ((sofar, cur), x) if x.nonEmpty => (sofar, cur copy (description = s"${nonnully(cur.description)}$x"))
case ((sofar, cur), _) if cur != empty => (cur :: sofar, empty)
case ((sofar, cur), _) => (sofar, empty)
}
Vor der Falte, schien es einfache Absätze zuerst zu tun. Ist das Imperativ zu denken?
object Test0 extends App with Sample {
def grafs(ss: Iterator[String]): List[List[String]] = {
val (g, rest) = ss dropWhile (_.isEmpty) span (_.nonEmpty)
val others = if (rest.nonEmpty) grafs(rest) else Nil
g.toList :: others
}
def toProject(ss: List[String]): Project = {
var p = Project("", "", "")
for (line <- ss; parts = line split '=') parts match {
case Array("User", u) => p = p.copy(user = u)
case Array("Project", n) => p = p.copy(name = n)
case Array(k, _) => sys error s"Bad keyword $k"
case Array(text) => p = p.copy(description = s"${p.description} $text")
}
p
}
val ps = grafs(sample.lines) map toProject
Console println ps
}
Können Sie ein Beispiel für test.txt und die Liste, die Sie erhalten möchten, angeben? – maks
Ich habe das Beispiel korrekt als Beispiel bezeichnet. :) –
Und was sollte der Inhalt der Ergebnisliste sein? – maks