带有Swift字符类型的NSCharacterSet.characterIsMember()

Gre*_*ley 32 swift

想象一下,你有一个Swift Character类型的实例,你想确定它是否是一个成员NSCharacterSet.NSCharacterSetcharacterIsMember方法需要unichar,所以我们需要从获得Characterunichar.

我能提出的唯一解决方案是以下,c我在哪里Character:

let u: unichar = ("\(c)" as NSString).characterAtIndex(0)
if characterSet.characterIsMember(u) {
    dude.abide()
}
Run Code Online (Sandbox Code Playgroud)

我看着Character但没有任何东西从我身上跳出来作为一种从中获取的方式unichar.这可能是因为Character更通用unichar,所以直接转换不安全,但我只是在猜测.

如果我迭代整个字符串,我会做这样的事情:

let s = myString as NSString
for i in 0..<countElements(myString) {
    let u = s.characterAtIndex(i)
    if characterSet.characterIsMember(u) {
        dude.abide()
    }
}
Run Code Online (Sandbox Code Playgroud)

(警告:以上是伪代码,从来没有任何人经营过.)但这并不是我所要求的.

Aar*_*sen 22

我的理解是,这unichar是一种类型UInt16.A unichar只是一个数字.

我认为,你所面临的问题是,Character在斯威夫特可以由一个以上的Unicode"字符".因此,它不能转换为单个unichar值,因为它可能由两个unichars组成.您可以通过将a Character转换unichar为字符串并使用utf16属性将a 分解为单个值,如下所示:

let c: Character = "a"
let s = String(c)
var codeUnits = [unichar]()
for codeUnit in s.utf16 {
    codeUnits.append(codeUnit)
}
Run Code Online (Sandbox Code Playgroud)

这将产生一个阵列- codeUnits-的unichar值.

编辑:初始代码for codeUnit in s应该是什么时候for codeUnit in s.utf16

你可以整理一下并测试每个单独的unichar值是否在这样的字符集中:

let char: Character = "\u{63}\u{20dd}" // This is a 'c' inside of an enclosing circle
for codeUnit in String(char).utf16 {
    if NSCharacterSet(charactersInString: "c").characterIsMember(codeUnit) {
        dude.abide()
    } // dude will abide() for codeUnits[0] = "c", but not for codeUnits[1] = 0x20dd (the enclosing circle)
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您只对第一个(通常是唯一的)unichar值感兴趣:

if NSCharacterSet(charactersInString: "c").characterIsMember(String(char).utf16[0]) {
    dude.abide()
}
Run Code Online (Sandbox Code Playgroud)

或者,将其包装在一个函数中:

func isChar(char: Character, inSet set: NSCharacterSet) -> Bool {
    return set.characterIsMember(String(char).utf16[0])
}

let xSet = NSCharacterSet(charactersInString: "x")
isChar("x", inSet: xSet)  // This returns true
isChar("y", inSet: xSet)  // This returns false
Run Code Online (Sandbox Code Playgroud)

现在,让功能检验所有 unichar的组合字符值-这样一来,如果你有一个组合字符,该函数将只有两个基本字符和组合字符存在返回true:

func isChar(char: Character, inSet set: NSCharacterSet) -> Bool {
    var found = true
    for ch in String(char).utf16 {
        if !set.characterIsMember(ch) { found = false }
    }
    return found
}

let acuteA: Character = "\u{e1}"                   // An "a" with an accent
let acuteAComposed: Character = "\u{61}\u{301}"    // Also an "a" with an accent

// A character set that includes both the composed and uncomposed unichar values
let charSet = NSCharacterSet(charactersInString: "\u{61}\u{301}\u{e1}")

isChar(acuteA, inSet: charSet)           // returns true
isChar(acuteAComposed, inSet: charSet)   // returns true (both unichar values were matched
Run Code Online (Sandbox Code Playgroud)

最后一个版本很重要.如果你Character是一个组合字符,你必须检查字符集中是否存在基本字符("a")和组合字符(急性重音),否则你会得到误报.

  • 几天前我在这个兔子洞里走了下来,我还没有回来:) (4认同)
  • 更短:`let units = [unichar](String(char).utf16)` (3认同)

mat*_*att 12

我会将角色视为一个字符串,让Cocoa完成所有工作:

func charset(cset:NSCharacterSet, containsCharacter c:Character) -> Bool {
    let s = String(c)
    let ix = s.startIndex
    let ix2 = s.endIndex
    let result = s.rangeOfCharacterFromSet(cset, options: nil, range: ix..<ix2)
    return result != nil
}
Run Code Online (Sandbox Code Playgroud)

以下是如何使用它:

let cset = NSCharacterSet.lowercaseLetterCharacterSet()
let c : Character = "c"
let ok = charset(cset, containsCharacter:c) // true
Run Code Online (Sandbox Code Playgroud)

  • 这可以简化为`let result = s.rangeOfCharacterFromSet(cset)`因为"options:"和"range:"是(现在?)*可选*参数. (3认同)