Как найти все вхождения подмножества строк в другой строке и заменить их чем-то другим?(например: замена эмоции) - PullRequest
1 голос
/ 02 июня 2019

Я создаю функцию чата для своего приложения, и у нас есть набор пользовательских смайликов.

Если пользователь вводит ярлык для одного из этих эмоций в своем комментарии, мы должны быть в состоянии обнаружитьярлыки в порядке появления и замените их на соответствующие эмоции.

Например.

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:) есть, чтобы найти диапазон подстроки, но использование этого кажется супер неэффективным, учитывая, что у нас могут быть десятки смайликов.


ОБНОВЛЕНИЕ:

Имейте в виду, что «ключи» (ярлыки) эмоций могут конфликтовать, поэтому перебор словаря эмоций не будет решением.Я изменил пример кода, чтобы отразить это.

1 Ответ

1 голос
/ 02 июня 2019

Регулярное выражение может использоваться, чтобы найти все вхождения любого из словарных ключей, например

(app|happy)

Шаблон границы слова \b можно использовать для сопоставления только полных слов:

\b(app|happy)\b

Комбинируя этот подход с кодом из Заменив соответствующие значения регулярного выражения в строке на правильное значение из словаря , мы получим следующую реализацию:

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 :)!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...