7

現在、スキャナーとパーサーを使用しており、ASCII 文字の文字を受け入れるパーサーが必要なので、char.isLetter.

私は自分で2つの解決策を思いつきました。私はそれらの両方が好きではありません。

正規表現

def letter = elem("ascii letter", _.toString.matches("""[a-zA-Z]"""))

これは、このような単純なことを正規表現でチェックするのはかなり「やり過ぎ」のようです。

レンジチェック

def letter = elem("ascii letter", c => ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))

私の意見では、これがJavaで進むべき道です。しかし、それは実際には読めません。

この問題に対する、よりクリーンでより Scala に似た解決策はありますか? この場合は問題にならないので、パフォーマンスについてはあまり心配していません。

4

4 に答える 4

17

Char.isLetterあなたはASCII文字だけが欲しいので使えないと言います。7 ビットの ASCII 文字範囲に制限しないのはなぜですか?

def isAsciiLetter(c: Char) = c.isLetter && c <= 'z'

リーダーが非文字を含む ASCII をチェックしたい場合は、次のようにします。

def isAscii(c: Char) = c.toInt <= 127
于 2013-03-15T22:42:52.237 に答える
2

最終的に何を選択するかに関係なく、読みやすさとパフォーマンスのために、「ASCII 文字である」という定義を抽象化することをお勧めします。例えば:

object Program extends App {
  implicit class CharProperties(val ch: Char) extends AnyVal {
    def isASCIILetter: Boolean =
      (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
  }
  println('x'.isASCIILetter)
  println('0'.isASCIILetter)
}

または、ASCII 文字をセットとして記述したい場合:

object Program extends App {
  object CharProperties {
    val ASCIILetters = ('a' to 'z').toSet ++ ('A' to 'Z').toSet
  }
  implicit class CharProperties(val ch: Char) extends AnyVal {
    def isASCIILetter: Boolean =
      CharProperties.ASCIILetters.contains(ch)
  }
  println('x'.isASCIILetter)
  println('0'.isASCIILetter)
}

わかりやすい名前で明示的な関数を使用すると、どちらの方法でも意図が明確になり、パフォーマンスの高い実装を選択できます (ただし、上記の 2 つのバージョンのパフォーマンスの違いは最小限に抑えられるはずです)。

于 2013-03-15T21:55:39.257 に答える
0

2番目のものは次のように書くことができます:

def letter = elem("ascii letter", c => ('a' to 'z') ++ ('A' to 'Z') contains c)

読みやすくなりますが、パフォーマンスは低下します。

++または、かろうじて平易な英語のように、あなたがおびえている場合:

c => ('a' to 'z') union ('A' to 'Z') contains c
于 2013-03-15T18:55:11.710 に答える
-1

別の - まあ - エレガントな解決策は、最小/最大を使用することです:

c => 'A'.max(c.toUpper) == 'Z'.min(c.toUpper)

また

c => 'A'.max(c) == 'Z'.min(c) || 'a'.max(c) == 'z'.min(c)
于 2013-03-15T20:37:02.513 に答える