現在str.toLowerCase.split("[\\s\\W]+")
、空白と句読点を取り除くために使用していますが、1 つにしてこの処理から除外したい特別なクラスの文字列があります。
[[...multiple words...]]
例:
[[Genghis Khan]]
のままにする必要があります
[[Genghis Khan]]
どのような正規表現を使用すればよいですか?
あなたの正規表現はそれほど遠くありません:
def tokenize(s: String) = """\w+|(\[\[[^\]]+\]\])""".r.findAllIn(s).toList
その後:
scala> tokenize("[[Genghis Khan]] founded the [[Mongol Empire]].")
res1: List[String] = List([[Genghis Khan]], founded, the, [[Mongol Empire]])
ただし、これは Scala のパーサー コンビネーターの優れた使用例です。
import scala.util.parsing.combinator._
object Tokenizer extends RegexParsers {
val punc = "[,;:\\.]*".r
val word = "\\w+".r
val multiWordToken = "[[" ~> "[^\\]]+".r <~ "]]"
val token = (word | multiWordToken) <~ punc
def apply(s: String) = parseAll(token+, s)
}
同様に、次のようになります。
scala> Tokenizer("[[Genghis Khan]] founded the [[Mongol Empire]].").get
res2: List[String] = List(Genghis Khan, founded, the, Mongol Empire)
個人的には、パーサー コンビネーター バージョンの方が好きです。これは、実質的に自己文書化されており、拡張と保守がはるかに簡単です。
[[
これは、またはのいずれかで最初に分割される関数です]]
。これを行うと、分割されたアイテムが引用符で囲まれていない文字列と引用符で囲まれた文字列の間で交互になります(つまり、2番目、4番目などのアイテムが「引用符で囲まれます」)。次に、このリストをトラバースして、引用符で囲まれたアイテムをそのままにして、空白で引用符で囲まれていないアイテムを分割できます。
def mySplit(s: String) =
"""(\[\[)|(\]\])""".r.split(s).zipWithIndex.flatMap {
case (unquoted, i) if i%2==0 => unquoted.trim.split("\\s+")
case (quoted, _) => List(quoted)
}.toList.filter(_.nonEmpty)
mySplit("this [[is]] the first [[test string]].") // List(this, is, the, first, test string, .)
mySplit("[[this]] and [[that]]") // List(this, and, that)
mySplit("[[this]][[that]][[the other]]") // List(this, that, the other)
[[ ]]
最終出力にを含める場合は、上記List(quoted)
を次のように変更します。List("[[" + quoted + "]]")
Split はコンテキストを処理しないため、これを処理する方法ではありません。あなたはこれを書いたかもしれません:
str.toLowerCase.split("(?<!\\[\\[([^]]|\\][^]])*\\]?)[\\s\\W]+")
これは、 が先行せず、[[
その後に 以外]]
が続くスペースで分割されますが、Java は可変サイズの後読みを好みません。
私の意見では、これを処理する最善の方法は、本当に速度が必要でない限り、パーサーを作成することです。Travis Brownが提案したような正規表現を使用します(彼は回答でパーサーも示しました)。