【发布时间】:2020-06-22 00:43:07
【问题描述】:
我有一个可以包含任意 Unicode 字符的字符串,我想获得该字符串的 前缀,其 UTF-8 编码长度尽可能接近 32 个字节,同时仍然是有效的 UTF-8 并且不改变字符的含义(即不切断扩展的字素簇)。
考虑这个正确的示例:
let string = "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}\u{1F1EA}\u{1F1FA}"
print(string) // ????????????????????????????????????
print(string.count) // 2
print(string.utf8.count) // 36
let prefix = string.utf8Prefix(32) // <-- function I want to implement
print(prefix) // ????????????????????????????
print(prefix.count) // 1
print(prefix.utf8.count) // 28
print(string.hasPrefix(prefix)) // true
这个错误实现的例子:
let string = "ar\u{1F3F4}\u{200D}\u{2620}\u{FE0F}\u{1F3F4}\u{200D}\u{2620}\u{FE0F}\u{1F3F4}\u{200D}\u{2620}\u{FE0F}"
print(string) // ar????☠️????☠️????☠️
print(string.count) // 5
print(string.utf8.count) // 41
let prefix = string.wrongUTF8Prefix(32) // <-- wrong implementation
print(prefix) // ar????☠️????☠️????
print(prefix.count) // 5
print(prefix.utf8.count) // 32
print(string.hasPrefix(prefix)) // false
有什么优雅的方法可以做到这一点? (除了试错)
【问题讨论】:
-
我不确定我理解前缀是什么意思。在获得 32 字节大小之前,您可以使用替代形式的前缀(重复或替代)。您可以查看有关此类特殊情况的 unicode(例如,一种长度为 2 字节,另一种长度为 3 字节)
-
@GiacomoCatenazzi 前缀是从起始索引开始的子字符串。有许多这样的“特殊情况”,它们的字节数可能超过 3 个字节(就像在我的示例中一样?????????????????????????????? ?? 有 28 个字节)
-
@MJK:我的意思是:有各种 修饰符,长度为 2 到 4 个字节。 Unicode 建议不要有超过 16 或 32 个(现在我不记得了)代码点,但是“unicode 键盘”可以插入它们,为单个字符提供无限长度的 unicode 序列 [unicode 字符串总是可以标准化的另一个原因] .无论如何,我建议您从 Unicode 代码点开始(稍后再考虑 UTF-8 编码)。
-
阅读答案,我仍然认为我没有得到您的要求。也许与unicode.org/reports/tr29 相关,然后通过添加将被忽略的组合代码点来进行归一化的逆操作?
-
@GiacomoCatenazzi 我不明白有什么不明白的。我想要一个带有给定字符串的前 n 个字符(即 Swift-
Charactersaka.ext.grapheme clusters)的前缀,以便该前缀的 UTF-8 编码最长为 32 个字节,而n 尽可能大。
标签: swift string unicode utf-8