快速将'Character'转换为'Unicode.Scalar'



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

Xcode 给出错误:

无法将类型"String.Element"(又名"字符")的值转换为指定类型"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
}

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

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

// Assuming...
var name: String = "..."
// ...then...
name.unicodeScalars.removeAll(where: { !CharacterSet.alphanumerics.contains($0) })

单个Character可以包含多个UnicodeScalar,因此您需要遍历所有这些并检查它们是否包含在CharacterSet.alphanumerics中。

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

测试输入:let name = "asd 1"

测试输出:"asd1"

没有var或双负:

let filteredName = String(name.unicodeScalars.filter {
CharacterSet.alphanumerics.contains($0)
})

最新更新