【问题标题】:UTF8 String length and indices in Go vs SwiftGo vs Swift 中的 UTF8 字符串长度和索引
【发布时间】:2018-10-12 16:55:53
【问题描述】:

我在 Go 和 Swift 中有处理字符串的应用程序,例如查找子字符串及其索引。起初,即使使用多字节字符(例如表情符号),它也能很好地工作,使用 Go 的 utf8.RuneCountInString() 和 Swift 的原生字符串。

但是有一些 UTF8 字符会破坏字符串长度和子字符串的索引,例如一个字符串"Lorem ????????✌️???? ipsum":

Go 的 utf8.RuneCountInString("Lorem ????????✌️???? ipsum") 返回 17,ipsum 的起始索引为 12。

Swift 的"Lorem ????????✌️???? ipsum".count 返回 16,ipsum 的起始索引是 11。

使用 Swift String 的 utf8utf16 或强制转换为 NSString 也会给出不同的长度和索引。还有其他表情符号由多个其他表情符号组成,例如??????‍????‍??????‍????这给出了更有趣的数字。

这适用于 Go 1.8 和 Swift 4.1。

有没有什么方法可以用 Go 和 Swift 获得相同的字符串长度和子字符串的索引?

编辑

我根据@MartinR 的出色回答创建了一个 Swift 字符串扩展:

extension String {
    func runesRangeToNSRange(from: Int, to: Int) -> NSRange {
        let length = to - from
        let start = unicodeScalars.index(unicodeScalars.startIndex, offsetBy: from)
        let end = unicodeScalars.index(start, offsetBy: length)
        let range = start..<end

        return NSRange(range, in: self)
    }
}

【问题讨论】:

  • 请注意,NSRange 仍然是另一回事:它来自 NSString 并计算 UTF-16 代码单元。
  • @MartinR 是的,我知道。我需要NSRange,所以我可以将它与TTTAttributedLabel 一起使用。 Apple 给了我们太多的范围和字符串,结合正则表达式使用起来很愉快:(再次感谢。

标签: swift string go utf-8


【解决方案1】:

在 Swift 中,Character 是一个“扩展字素簇”,“?”、“?”、“✌️”、“?”、“?‍?‍?‍?”中的每一个都算作一个字符.

我没有使用 Go 的经验,但我从 Strings, bytes, runes and characters in Go 了解到, “rune”是一个 Unicode 码位,本质上对应于 Swift 中的 UnicodeScalar

在您的示例中,差异来自“✌️” 算作单个 Swift 字符,但由两个 Unicode 标量构建:

print("✌️".count) // 1
print("✌️".unicodeScalars.count) // 2

这是一个如何计算长度和偏移量的示例 Unicode 标量术语:

let s = "Lorem ??✌️? ipsum"
print(s.unicodeScalars.count) // 17

if let idx = s.range(of: "ipsum") {
    print(s.unicodeScalars.distance(from: s.startIndex, to: idx.lowerBound)) // 12
}

如您所见,这给出的数字与您在 Go 中的示例相同。

【讨论】:

  • 感谢unicodeScalars!我根据您的评论(现已删除)创建了一个 Swift 字符串扩展。现在一切正常。 UTF 是“伟大的”...
【解决方案2】:

A rune in Go identifies a specific UTF-8 code point;这并不一定意味着它将 1:1 映射到视觉上不同的字符。某些字符可能由多个符文/代码点组成,因此计数符文可能无法提供您对字符串的目视检查所期望的内容。我不知道 "some text".count 在 Swift 中的实际意义,所以我无法提供任何比较。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-16
    相关资源
    最近更新 更多