Swift 似乎试图反对字符串由原子字符数组组成的概念,这对许多用途都有意义,但是有大量的编程涉及为所有实际目的选择 ASCII 数据结构: 特别是文件 I/O。缺少用于指定字 rune 字的内置语言功能似乎是一个巨大的漏洞,即没有 C/Java/etc-esque 的类似物:
String foo="a"
char bar='a'
这很不方便,因为即使将字符串转换为字符数组,也不能执行以下操作:
let ch:unichar = arrayOfCharacters[n]
if ch >= 'a' && ch <= 'z' {...whatever...}
一个相当 hacky 的解决方法是做这样的事情:
let LOWCASE_A = ("a" as NSString).characterAtIndex(0)
let LOWCASE_Z = ("z" as NSString).characterAtIndex(0)
if ch >= LOWCASE_A && ch <= LOWCASE_Z {...whatever...}
这行得通,但显然它很丑陋。谁有更好的方法?
最佳答案
Character
可以从 String
创建,只要这些 String
仅由单个字符组成。而且,由于 Character
实现了 ExtendedGraphemeClusterLiteralConvertible
,Swift 会在赋值时自动为你做这件事。因此,要在 Swift 中创建一个 Character
,您可以简单地执行以下操作:
let ch: Character = "a"
然后,您可以使用 IntervalType
(由 Range
operators 生成)的 contains
方法来检查字符是否在您要查找的范围内:
if ("a"..."z").contains(ch) {
/* ... whatever ... */
}
例子:
let ch: Character = "m"
if ("a"..."z").contains(ch) {
println("yep")
} else {
println("nope")
}
输出:
yep
更新:正如@MartinR 所指出的,Swift 字符的排序是基于 Unicode Normalization Form D 的。这与 ASCII 字符代码的顺序不相同。在您的特定情况下, a
和 z
之间的字符比直接 ASCII 中的字符多(例如 ä
)。查看@MartinR 的回答 here了解更多信息。
如果您需要检查一个字符是否在两个 ASCII 字符代码之间,那么您可能需要执行与原始解决方法类似的操作。但是,您还必须将 ch
转换为 unichar
而不是 Character
才能正常工作(请参阅 this question 了解更多信息在 Character
与 unichar
上:
let a_code = ("a" as NSString).characterAtIndex(0)
let z_code = ("z" as NSString).characterAtIndex(0)
let ch_code = (String(ch) as NSString).characterAtIndex(0)
if (a_code...z_code).contains(ch_code) {
println("yep")
} else {
println("nope")
}
或者,不使用 NSString
的更详细的方法:
let startCharScalars = "a".unicodeScalars
let startCode = startCharScalars[startCharScalars.startIndex]
let endCharScalars = "z".unicodeScalars
let endCode = endCharScalars[endCharScalars.startIndex]
let chScalars = String(ch).unicodeScalars
let chCode = chScalars[chScalars.startIndex]
if (startCode...endCode).contains(chCode) {
println("yep")
} else {
println("nope")
}
注意:这两个示例仅在字符仅包含单个代码点时才有效,但是,只要我们仅限于 ASCII,那应该不是问题.
关于swift - 有没有一种干净的方法可以在 Swift 中指定字 rune 字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26105301/