2

テキストファイルは、Scalaパターンマッチングと正規表現を使用して、1行ずつ解析する必要があります。"names:\t"行が後続のタブで始まる場合は、名前をSeq[String](または同様のもの)として指定する必要があります。

ここに機能しないコード例があります:

val Names = "^names:(?:\t([a-zA-Z0-9_]+))+$".r

"names:\taaa\tbbb\tccc" match {
  case Names(names @ _*) => println(names)
  // […] other cases
  case _ => println("no match")
}

出力:List(ccc)
必要な出力:List(aaa, bbb, ccc)

次のコードは希望どおりに機能します…</p>

object NamesObject {
  private val NamesLine = "^names:\t([a-zA-Z0-9_]+(?:\t[a-zA-Z0-9_]+)*)$".r

  def unapplySeq(s: String): Option[Seq[String]] = s match {
    case NamesLine(nameString) => Some(nameString.split("\t"))
    case _ => None
  }
}

"names:\taaa\tbbb\tccc" match {
  case NamesObject(names @ _*) => println(names)
  // […] other cases
  case _ => println("no match")
}

出力(必要に応じて):WrappedArray(aaa, bbb, ccc)

知りたいのですが、これは、最初の、しかし機能しないコード例のように、を作成せずに簡単な方法で可能ですか?object

4

2 に答える 2

1

作業中の正規表現を使用します。(はの\w事前定義された文字クラスです[a-zA-Z0-9_]

  val Names = """names:\t(\w+(?:\t\w+)*)""".r
  "names:\taaa\tbbb\tccc" match {
    case Names(names) => println(names.split("\t") toSeq)
    case _ => println("no match")
  }

ファースト、セカンド、テールバインディングで、

  val Names = """names:\t(\w+)?\t?(\w+)?\t?((?:\w+?\t?)*)""".r
  "names:\taaa\tbbb\tccc\tddd" match {
    case Names(first, second, tail) =>
      println(first + ", " + second + ", " + (tail.split("\t") toSeq));
    case _ => println("no match")
  }
于 2013-03-26T15:28:54.687 に答える
0

Randall Schulzが言ったように、正規表現を使用するだけでは不可能のようです。したがって、私の質問に対する簡単な答えはノーです。

私の現在の解決策は次のとおりです。私はこのクラスを使用しています…</p>

class SeparatedLinePattern(Pattern: Regex, separator: String = "\t") {
  def unapplySeq(s: String): Option[Seq[String]] = s match {
    case Pattern(nameString) => Some(nameString.split(separator).toSeq)
    case _ => None
  }
}

…パターンを作成するには:

val Names = new SeparatedLinePattern("""names:\t([A-Za-z]+(?:\t[A-Za-z]+)*)""".r)
val Ints = new SeparatedLinePattern("""ints:\t(\d+(?:\t\d+)*)""".r)
val ValuesWithID = new SeparatedLinePattern("""id-value:\t(\d+\t\w+(?:\t\d+\t\w+)*)""".r)

これらを非常に柔軟に使用する方法の例を次に示します。

val testStrings = List("names:\taaa", "names:\tbbb\tccc", "names:\tddd\teee\tfff\tggg\thhh",
                       "ints:\t123", "ints:\t456\t789", "ints:\t100\t200\t300",
                       "id-value:\t42\tbaz", "id-value:\t2\tfoo\t5\tbar\t23\tbla")

for (s <- testStrings) s match {
  case Names(name) => println(s"The name is '$name'")
  case Names(a, b) => println(s"The two names are '$a' and '$b'")
  case Names(names @ _*) => println("Many names: " + names.mkString(", "))

  case Ints(a) => println(s"Just $a")
  case Ints(a, b) => println(s"$a + $b == ${a.toInt + b.toInt}")
  case Ints(nums @ _*) => println("Sum is " + (nums map (_.toInt)).sum)

  case ValuesWithID(id, value) => println(s"ID of '$value' is $id")
  case ValuesWithID(values @ _*) => println("As map: " + (values.grouped(2) map (x => x(0).toInt -> x(1))).toMap)

  case _ => println("No match")
}

出力:

The name is 'aaa'
The two names are 'bbb' and 'ccc'
Many names: ddd, eee, fff, ggg, hhh
Just 123
456 + 789 == 1245
Sum is 600
ID of 'baz' is 42
As map: Map(2 -> foo, 5 -> bar, 23 -> bla)
于 2013-03-27T09:03:29.257 に答える