我目前正在使用扫描仪和解析器,需要一个接受ASCII字母字符的解析器 - 所以我不能使用char.isLetter
。
我自己想出了两个解决方案。我不喜欢他们两个。
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的解决方案?我并不担心性能,因为在这种情况下并不重要。
答案 0 :(得分:16)
你说你不能使用Char.isLetter
因为你只想要ASCII字母。为什么不将它限制为7位ASCII字符范围?
def isAsciiLetter(c: Char) = c.isLetter && c <= 'z'
如果读者想要检查ASCII包括非字母,那么:
def isAscii(c: Char) = c.toInt <= 127
答案 1 :(得分:2)
无论你最终选择什么,我建议为了可读性和性能而抽象出“是一个ASCII字母”的定义。 E.g:
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)
}
一旦您使用具有可理解名称的显式函数,您的意图应该是明确的,并且您可以选择具有更好性能的实现(尽管上述两个版本之间的任何性能差异应该相当小)。 / p>
答案 2 :(得分:0)
第二个可以写成:
def letter = elem("ascii letter", c => ('a' to 'z') ++ ('A' to 'Z') contains c)
它更具可读性,但性能较差。
或者,如果你对++
感到害怕,那几乎不是简单的英语:
c => ('a' to 'z') union ('A' to 'Z') contains c
答案 3 :(得分:-1)
另一个 - 优雅的解决方案可能是使用min / max:
c => 'A'.max(c.toUpper) == 'Z'.min(c.toUpper)
或
c => 'A'.max(c) == 'Z'.min(c) || 'a'.max(c) == 'z'.min(c)