我有一个检测字符串中url的方法,并返回url和可以找到它们的范围。一切都很完美,直到字符串上有表情符号。例如:
subcribe
由于表情符号,从文本中提取的网址为http://youtu.be/SW_d3fGz1而不是http://youtu.be/SW_d3fGz1hk。我认为最简单的解决方案是用空格字符替换字符串上的表情符号(因为我需要范围对于某些文本样式的东西是正确的)。问题是,使用Swift非常难以实现(很可能我的Swift String API缺乏能力)。
我一直试图这样做,但似乎我无法从unicode点数组中创建一个字符串:
"I'm gonna do this callenge as soon as I can swing again \n http://youtu.be/SW_d3fGz1hk"
我是否以错误的方式接近这个问题?取代表情符号是最好的解决方案吗?如果是这样,我该怎么做?
答案 0 :(得分:6)
您可以使用模式匹配(用于表情符号模式)过滤掉String
中的表情符号字符。
extension String {
var emojilessStringWithSubstitution: String {
let emojiPatterns = [UnicodeScalar(0x1F601)...UnicodeScalar(0x1F64F),
UnicodeScalar(0x2702)...UnicodeScalar(0x27B0)]
return self.unicodeScalars
.filter { ucScalar in !(emojiPatterns.contains{ $0 ~= ucScalar }) }
.reduce("") { $0 + String($1) }
}
}
/* example usage */
let str = "I'm gonna do this callenge as soon as I can swing again \n http://youtu.be/SW_d3fGz1hk"
print(str.emojilessStringWithSubstitution)
/* I'm gonna do this callenge as soon as I can swing again
http://youtu.be/SW_d3fGz1hk */
请注意,上述内容仅使用了问题中提供的表情符号间隔,并不代表所有表情符号,但该方法是通用的,可以通过在{{1}中包含额外的表情符号间隔来快速扩展。数组。
我意识到再次阅读你的问题,你更喜欢用空格字符替换表情符号,而不是删除它们(上面的过滤解决方案就是这样)。我们可以通过使用条件返回emojiPatterns
操作替换上面的.filter
操作来实现此目的,就像在您的问题中一样
.map
如上所述,根据你对这篇文章的评论(列出这些间隔),已经扩展了现有的表情符号间隔,这样表情符号检查现在可能是详尽无遗的。
答案 1 :(得分:3)
Swift 4:
extension String {
func stringByRemovingEmoji() -> String {
return String(self.filter { !$0.isEmoji() })
}
}
extension Character {
fileprivate func isEmoji() -> Bool {
return Character(UnicodeScalar(UInt32(0x1d000))!) <= self && self <= Character(UnicodeScalar(UInt32(0x1f77f))!)
|| Character(UnicodeScalar(UInt32(0x2100))!) <= self && self <= Character(UnicodeScalar(UInt32(0x26ff))!)
}
}
答案 2 :(得分:2)
快捷键5
请勿使用这种where
方法来检测hardcoded
。在emojis
中,您可以轻松完成
Swift 5
答案 3 :(得分:0)
表情符号按Unicode分类为符号。字符集通常用于搜索操作。因此,我们将使用“字符集”作为符号的属性。
var emojiString = "Hey there , welcome"
emojiString = emojiString.components(separatedBy: CharacterSet.symbols).joined()
print(emojiString)
输出为
Hey there , welcome
现在观察表情符号被一个空格替换,因此有两个空格,我们通过以下方式替换它
emojiString.replacingOccurrences(of: " ", with: " ")
上述方法将“两个空白”的参数替换为“单个空白”
答案 4 :(得分:0)
我发现上述给出的解决方案不适用于某些字符,例如️♂️和。
要查找表情符号范围,我使用正则表达式将full list of emoji characters转换为只有十六进制值的文件。然后,我将它们转换为十进制格式并对其进行了排序。最后,我编写了一个脚本来查找范围。
这是isEmoji()
的最终Swift扩展。
extension Character {
func isEmoji() -> Bool {
let emojiRanges = [
(8205, 11093),
(12336, 12953),
(65039, 65039),
(126980, 129685)
]
let codePoint = self.unicodeScalars[self.unicodeScalars.startIndex].value
for emojiRange in emojiRanges {
if codePoint >= emojiRange.0 && codePoint <= emojiRange.1 {
return true
}
}
return false
}
}
作为参考,这是我编写的python脚本,用于将十六进制字符串解析为整数,然后找到范围。
转换为十六进制的py
decimals = []
with open('hex.txt') as hexfile:
for line in hexfile:
num = int(line, 16)
if num < 256:
continue
decimals.append(num)
decimals = list(set(decimals))
decimals.sort()
with open('decimal.txt', 'w') as decimalfile:
for decimal in decimals:
decimalfile.write(str(decimal) + "\n")
make-ranges.py
first_line = True
range_start = 0
prev = 0
with open('decimal.txt') as hexfile:
for line in hexfile:
if first_line:
prev = int(line)
range_start = prev
first_line = False
continue
curr = int(line)
if prev + 1000 < curr: # 100 is abitrary to reduce number of ranges
print("(" + str(range_start) + ", " + str(prev) + ")")
range_start = curr
prev = curr
答案 5 :(得分:0)
获取所有表情符号比您想象的要复杂。有关如何确定哪些字符是表情符号的更多信息,请查看此stackoverflow帖子或this article。
基于这些信息,我建议使用Character上的扩展名,以使我们更容易理解哪些字符是表情符号。然后添加一个字符串扩展名,以轻松地将找到的表情符号替换为另一个字符。
extension Character {
var isSimpleEmoji: Bool {
guard let firstProperties = unicodeScalars.first?.properties else {
return false
}
return unicodeScalars.count == 1 &&
(firstProperties.isEmojiPresentation ||
firstProperties.generalCategory == .otherSymbol)
}
var isCombinedIntoEmoji: Bool {
return unicodeScalars.count > 1 &&
unicodeScalars.contains {
$0.properties.isJoinControl ||
$0.properties.isVariationSelector
}
}
var isEmoji: Bool {
return isSimpleEmoji || isCombinedIntoEmoji
}
}
extension String {
func replaceEmoji(with character: Character) -> String {
return String(map { $0.isEmoji ? character : $0 })
}
}
使用它将变成:
"Some string ??? with emoji".replaceEmoji(with: " ")