Swift 将“字符”转换为“Unicode.Scalar”

Pet*_*isu 7 string character swift unicodescalar

我正在尝试从字符串中过滤出非字母字符,但遇到了CharacterSet使用Unicode.Scalar和字符串组成的问题Character.

Xcode 给出了错误:

无法将“String.Element”(又名“Character”)类型的值转换为指定类型“Unicode.Scalar”?

let name = "name"
let allowedCharacters = CharacterSet.alphanumerics
let filteredName = name.filter { (c) -> Bool in
    if let s: Unicode.Scalar = c { // cannot convert
        return !allowedCharacters.contains(s)
    }
    return true
}
Run Code Online (Sandbox Code Playgroud)

Jer*_*cht 18

CharacterSet不幸的是,它有一个继承自 Objective C 的名称。实际上,它是一组Unicode.Scalars,而不是 of Characters(Unicode 术语中的“扩展字素簇”)。这是必要的,因为虽然有一组有限的 Unicode 标量,但有无限数量的可能的字素簇。例如,e + ?? + ?? + ?? ... 无限期仍然只是一个集群。因此,不可能详尽地列出所有可能的集群,并且通常不可能列出具有特定属性的它们的子集。问题中的集合操作必须改用标量(或至少使用从组件标量派生的定义)。

在 Swift 中,Strings 有一个unicodeScalars属性可以在标量级别对字符串 a 进行操作,并且该属性是直接可变的。这使您可以执行以下操作:

// Assuming...
var name: String = "..."

// ...then...
name.unicodeScalars.removeAll(where: { !CharacterSet.alphanumerics.contains($0) })
Run Code Online (Sandbox Code Playgroud)


Dáv*_*tor 10

一个Character可以由多个UnicodeScalars组成,因此您需要遍历所有这些并检查它们是否包含在CharacterSet.alphanumerics.

let allowedCharacters = CharacterSet.alphanumerics
let filteredName = name.filter { (c) -> Bool in
    return !c.unicodeScalars.contains(where: { !allowedCharacters.contains($0)})
}
Run Code Online (Sandbox Code Playgroud)

测试输入: let name = "asd1"

测试输出: "asd1"

  • 天哪,我讨厌迅速 (6认同)
  • @PeterLapisu 在现代字符串世界中不仅由 ASCII 字符组成,正确处理 `Unicode` 字符是必要的邪恶 (3认同)
  • 但一个 CharacterSet 不能与 Character 一起工作是荒谬的 (2认同)