【问题标题】:How to find all occurrences of a subset of strings within another string and replace them with something else? (e.g: Emote replacement)如何在另一个字符串中查找所有出现的字符串子集并将它们替换为其他字符串? (例如:表情替换)
【发布时间】:2019-10-18 03:55:02
【问题描述】:

我正在为我的应用创建聊天功能,我们有一组自定义表情符号。

如果用户在他们的评论中键入其中一种表情的快捷方式,我们需要能够按出现顺序检测快捷方式,并将其替换为正确的表情。

例如。

let emotes = [
    "app" : "[]"
    "happy" : ":)", 
]

let userComment = "I am happy"

let expectedResult = "I am :)" // "app" was not replaced because "happy"'s "h" was found first, hence it was evaluated before "app"

考虑到同一个表情可以多次出现在一条评论中,有没有一种有效的算法来实现这一点?

我知道有range(of:) 可以找到子字符串的范围,但是考虑到我们可能有几十个表情符号,使用它似乎效率非常低。


更新:

请注意,表情“键”(快捷方式)可能会发生冲突,因此遍历表情字典不会是答案。我更改了示例代码以反映这一点。

【问题讨论】:

  • 您要么必须循环遍历字符串多次,每次使用字典中的不同键,要么循环遍历字符串一次,但多次遍历字典。取决于你认为哪个会更长。您正在实施的表情数量或 cmets 的长度?
  • 循环搜索字典中的每个键不起作用,因为表情应该在字符串中出现时呈现。我还更新了这个问题,其中表情的“键”可能与另一个键发生碰撞。

标签: swift string algorithm pattern-matching substring


【解决方案1】:

正则表达式可用于查找任何字典键的所有匹配项,例如

(app|happy)

单词边界模式\b 可用于仅匹配完整的单词:

\b(app|happy)\b

将此方法与Replace matching regex values in string with correct value from dictionary 中的代码相结合,我们得到以下实现:

func replaceOccurrences(in string: String, fromDict dict: [String: String]) -> String {
    var result = string

    // A pattern matching any of the dictionary keys.
    let pattern = "\\b(" + dict.keys.map { NSRegularExpression.escapedPattern(for: $0)}
        .joined(separator: "|") + ")\\b"
    let regex = try! NSRegularExpression(pattern: pattern)
    let matches = regex.matches(in: string, range: NSRange(string.startIndex..., in: string))

    // Iterate in reverse to avoid messing up the ranges as the keys are replaced with the values.
    for match in matches.reversed() {
        if let range = Range(match.range, in: string) {
            // Extract key, look up replacement in dictionary, and replace in result string.
            if let replacement = dict[String(string[range])] {
                result.replaceSubrange(range, with: replacement)
            }
        }
    }

    return result
}

示例 1:

let emotes = [
    "happy" : ":)",
    "sad" : ":("
]

let userComment = "I am happy to meet you, but I am sad cos of this algorithm"
let result = replaceOccurrences(in: userComment, fromDict: emotes)
print(result) // I am :) to meet you, but I am :( cos of this algorithm

示例 2:

let emotes = [
    "app" : "[]",
    "happy" : ":)"
]

let userComment = "I am happy!"
let result = replaceOccurrences(in: userComment, fromDict: emotes)
print(result) // I am :)!

【讨论】:

  • 哇!这正是我想要的!只是一个问题,这种算法是“O(n)”吗?我不知道正则表达式模式匹配的复杂性是什么。不管怎样,谢谢! (我会将此标记为答案)
  • @AlexTanabe:我不知道正则表达式匹配是如何实现的。我强烈认为如果要替换很多字符串,它比单独搜索更有效。
猜你喜欢
  • 2013-12-22
  • 1970-01-01
  • 2013-07-10
  • 1970-01-01
  • 1970-01-01
  • 2013-01-07
  • 1970-01-01
  • 1970-01-01
  • 2013-12-29
相关资源
最近更新 更多