У меня есть список строк, содержащих запрещенные слова. Какой эффективный способ проверить, содержит ли строка какие-либо запрещенные слова, и удалить их из строки? На данный момент у меня так:
Это отлично работает для отдельных запрещенных слов, но не для фраз (например, more than one word). Любой экземпляр more than one word также должен быть удален. Альтернативой, которую я хотел попробовать, является использование метода List из списка, но он возвращает только логическое значение, а не индекс соответствующего слова. Если бы я мог получить индекс подходящего слова, я мог бы просто использовать String.Replace(bannedWords[i],"");
В чем эффективность? Представление? Длина кода? zmbq 08.04.2012
Проблема сводится к простому поиску и замене, пока вы не сделаете ключевую ошибку: thedailywtf.com/Articles/The-Clbuttic-Mistake-.aspx Kendall Frey 08.04.2012
что не так с вашим решением в отношении "более одного слова" - если оно перекрывается, вы можете отсортировать их по длине, от большего к меньшему? Более эффективным было бы "перечислить" до конца, но вам все равно нужно быть осторожным с "перекрытиями". NSGaga-mostly-inactive 08.04.2012
Простой String.Replace не будет работать, так как он удалит части слова. Если "секс" - запрещенное слово, а у вас есть слово "секстет", которое не запрещено, вы должны оставить его как есть.
С помощью Regex вы можете найти целые слова и фразы в тексте с
string text = "A sextet is a musical composition for six instruments or voices.".
string word = "sex";
var matches = Regex.Matches(text, @"(?<=\b)" + word + @"(?=\b)");
В этом случае коллекция спичек будет пустой.
Вы можете использовать метод Regex.Replace
foreach (string word in bannedWords) {
text = Regex.Replace(text, @"(?<=\b)" + word + @"(?=\b)", "")
}
Примечание. Я использовал следующий шаблон Regex
(?<=prefix)find(?=suffix)
где "префикс" и "суффикс" равны \b, что обозначает начало и конец слова.
Если ваши запрещенные слова или фразы могут содержать специальные символы, было бы безопаснее экранировать их с помощью Regex.Escape(word).
Используя идею @zmbq, вы можете создать шаблон Regex один раз с помощью
string pattern =
@"(?<=\b)(" +
String.Join(
"|",
bannedWords
.Select(w => Regex.Escape(w))
.ToArray()) +
@")(?=\b)";
var regex = new Regex(pattern); // Is compiled by default
а затем многократно применять его к разным текстам с помощью
string result = regex.Replace(text, "");
Ответ 2 · рейтинг 2 · Henk Holterman
Это не работает, потому что у вас противоречивые определения.
Когда вы хотите искать подпредложения, такие как more than one word, вы больше не можете разбивать по пробелам. Вам придется вернуться к String.IndexOf()
Ответ 3 · рейтинг 1 · zmbq
Если вам нужна производительность, я предполагаю, что вы беспокоитесь не о единовременной настройке, а о непрерывной производительности. Поэтому я бы создал одно огромное регулярное выражение, содержащее все запрещенные выражения, и убедился, что оно скомпилировано - это как установка.
Затем я попытался бы сопоставить его с текстом и заменить каждое совпадение пробелом или чем-то, чем вы хотите его заменить.
Причина этого в том, что большое регулярное выражение должно компилироваться во что-то, сравнимое с конечным автоматом, который вы создали бы вручную для решения этой проблемы, поэтому оно должно работать довольно хорошо.
Ответ 4 · Zafer
Почему бы вам не просмотреть список запрещенных слов и не найти каждое из них в строке с помощью метода string.IndexOf. Например, вы можете удалить запрещенные слова и фразы с помощью следующего фрагмента кода: