问题描述
我正在尝试解析 Twitch IRC 表情并从字符串中提取它。 Twitch IRC 消息提供了一个范围,它是字符串中表情的位置。示例:
string="Kappa abcdef";范围开始=0;范围结束=4
表示表情 Kappa 位于字符串“Kappa abcdef”中的索引 0 到 4 之间。
func extractEmoteName(from message: String,rangeStart: Int,rangeEnd: Int) -> String? {
guard
let indexStart = message.index(message.startIndex,offsetBy: rangeStart,limitedBy: message.endindex),let limitIndex = message.index(message.endindex,offsetBy: -1,limitedBy: message.startIndex),let indexEnd = message.index(message.startIndex,offsetBy: rangeEnd,limitedBy: limitIndex)
else {
print("out of bounds")
return nil
}
return String(message[indexStart ... indexEnd])
}
在示例字符串上使用它:extractEmoteName(from: "Kappa abcdef",rangeStart: 0,rangeEnd: 4)
将返回 Kappa
作为结果。
我在处理包含带有多个 unicode 标量的表情符号的字符串时遇到问题:
string="⚠️ Kappa";范围开始=3;范围结束=7
extractEmoteName(from: "⚠️ Kappa",rangeStart: 3,rangeEnd: 7) // prints "out of bounds"
同时,带有单个标量表情的消息解析得很好,因为 Twitch 提供的范围不同:
string="? 河童";范围开始=2;范围结束=6
extractEmoteName(from: "? Kappa",rangeStart: 2,rangeEnd: 6) // returns "Kappa"
应该在 extractEmoteName
中进行哪些更改以使其适用于所有表情符号字符?
解决方法
您需要使用 unicodeScalars
,它将以 unicode 标量表示字符串:
func extractEmoteName(from input: String,rangeStart: Int,rangeEnd: Int) -> String? {
let message = input.unicodeScalars
guard
let indexStart = message.index(message.startIndex,offsetBy: rangeStart,limitedBy: message.endIndex),let limitIndex = message.index(message.endIndex,offsetBy: -1,limitedBy: message.startIndex),let indexEnd = message.index(message.startIndex,offsetBy: rangeEnd,limitedBy: limitIndex)
else {
print("out of bounds")
return nil
}
return String(message[indexStart ... indexEnd])
,
您可以通过计算标量来实现。
func extractEmoteName(from message: String,rangeEnd: Int) -> String? {
guard rangeStart >= 0 && rangeStart <= rangeEnd else {
return nil
}
let scalars = message.unicodeScalars
let start = scalars.index(scalars.startIndex,offsetBy: rangeStart)
let end = scalars.index(scalars.startIndex,offsetBy: rangeEnd)
let nameScalars = scalars[start...end]
return String(nameScalars)
}