Как разбить текст на слова?
Пример текста:
"О, ты не можешь с этим поделать, - сказал Кот: - Мы все здесь сумасшедшие. Я псих. Ты злишься.
Слова в этой строке:
- О
- вы
- не может
- помощь
- что
- сказал
- Cat
- мы
- все
- безумен
- здесь
- Я
- безумен
- Вы
- безумен
Как разбить текст на слова?
Пример текста:
"О, ты не можешь с этим поделать, - сказал Кот: - Мы все здесь сумасшедшие. Я псих. Ты злишься.
Слова в этой строке:
Разделите текст на пробелы, затем пунктирную обрезку.
var text = "'Oh, you can't help that,' said the Cat: 'we're all mad here. I'm mad. You're mad.'";
var punctuation = text.Where(Char.IsPunctuation).Distinct().ToArray();
var words = text.Split().Select(x => x.Trim(punctuation));
Соответствует точно примеру.
Сначала удалите все специальные символы:
var fixedInput = Regex.Replace(input, "[^a-zA-Z0-9% ._]", string.Empty);
// This regex doesn't support apostrophe so the extension method is better
Тогда разделите это:
var split = fixedInput.Split(' ');
Для более простого решения С# для удаления специальных символов (которое вы можете легко изменить), добавьте этот метод расширения (я добавил поддержку апострофа):
public static string RemoveSpecialCharacters(this string str) {
var sb = new StringBuilder();
foreach (char c in str) {
if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '\'' || c == ' ') {
sb.Append(c);
}
}
return sb.ToString();
}
Тогда используйте это так:
var words = input.RemoveSpecialCharacters().Split(' ');
Вы будете удивлены, узнав, что этот метод расширения очень эффективен (несомненно, намного эффективнее, чем Regex), поэтому я предлагаю вам использовать его;)
Обновить
Я согласен, что это только английский подход, но чтобы сделать его совместимым с Юникодом, все что вам нужно сделать, это заменить:
(c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
С:
char.IsLetter(c)
Поддерживает Unicode,.Net также предлагает вам char.IsSymbol
и char.IsLetterOrDigit
для различных случаев
Просто добавьте вариацию на @Adam Fridental ответ, который очень хорош, вы можете попробовать это Regex:
var text = "'Oh, you can't help that,' said the Cat: 'we're all mad here. I'm mad. You're mad.'";
var matches = Regex.Matches(text, @"\w+[^\s]*\w+|\w");
foreach (Match match in matches) {
var word = match.Value;
}
Я считаю, что это самый короткий RegEx, который получит все слова
\w+[^\s]*\w+|\w
Если вы не хотите использовать объект Regex, вы можете сделать что-то вроде...
string mystring="Oh, you can't help that,' said the Cat: 'we're all mad here. I'm mad. You're mad.";
List<string> words=mystring.Replace(",","").Replace(":","").Replace(".","").Split(" ").ToList();
Вам все равно придется обрабатывать завершающий апостроф в конце "that",
Это одно из решений, я не использую какой-либо вспомогательный класс или метод.
public static List<string> ExtractChars(string inputString) {
var result = new List<string>();
int startIndex = -1;
for (int i = 0; i < inputString.Length; i++) {
var character = inputString[i];
if ((character >= 'a' && character <= 'z') ||
(character >= 'A' && character <= 'Z')) {
if (startIndex == -1) {
startIndex = i;
}
if (i == inputString.Length - 1) {
result.Add(GetString(inputString, startIndex, i));
}
continue;
}
if (startIndex != -1) {
result.Add(GetString(inputString, startIndex, i - 1));
startIndex = -1;
}
}
return result;
}
public static string GetString(string inputString, int startIndex, int endIndex) {
string result = "";
for (int i = startIndex; i <= endIndex; i++) {
result += inputString[i];
}
return result;
}
Вы можете попробовать использовать регулярное выражение для удаления апострофов, которые не окружены буквами (то есть одинарные кавычки), а затем с помощью статических методов Char
для удаления всех других символов. Вызывая регулярное выражение, вы можете сохранить апострофы сжатия (например, can't
), но удалите одинарные кавычки, как в 'Oh
.
string myText = "'Oh, you can't help that,' said the Cat: 'we're all mad here. I'm mad. You're mad.'";
Regex reg = new Regex("\b[\"']\b");
myText = reg.Replace(myText, "");
string[] listOfWords = RemoveCharacters(myText);
public string[] RemoveCharacters(string input)
{
StringBuilder sb = new StringBuilder();
foreach (char c in input)
{
if (Char.IsLetter(c) || Char.IsWhiteSpace(c) || c == '\'')
sb.Append(c);
}
return sb.ToString().Split(' ');
}
Если вы хотите использовать "для цикла", чтобы проверить каждый символ и сохранить все знаки препинания во входной строке, я создал этот класс. Метод GetSplitSentence() возвращает список SentenceSplitResult. В этом списке сохранены все слова и все знаки препинания и цифры. Каждая сохраненная пунктуация или цифры - это элемент списка. ПредложениеSplitResult.isAWord используется для проверки, является ли слово словом или нет. [Извините за мой английский]
public class SentenceSplitResult
{
public string word;
public bool isAWord;
}
public class StringsHelper
{
private readonly List<SentenceSplitResult> outputList = new List<SentenceSplitResult>();
private readonly string input;
public StringsHelper(string input)
{
this.input = input;
}
public List<SentenceSplitResult> GetSplitSentence()
{
StringBuilder sb = new StringBuilder();
try
{
if (String.IsNullOrEmpty(input)) {
Logger.Log(new ArgumentNullException(), "GetSplitSentence - input is null or empy");
return outputList;
}
bool isAletter = IsAValidLetter(input[0]);
// Each char i checked if is a part of a word.
// If is YES > I can store the char for later
// IF is NO > I Save the word (if exist) and then save the punctuation
foreach (var _char in input)
{
isAletter = IsAValidLetter(_char);
if (isAletter == true)
{
sb.Append(_char);
}
else
{
SaveWord(sb.ToString());
sb.Clear();
SaveANotWord(_char);
}
}
SaveWord(sb.ToString());
}
catch (Exception ex)
{
Logger.Log(ex);
}
return outputList;
}
private static bool IsAValidLetter(char _char)
{
if ((Char.IsPunctuation(_char) == true) || (_char == ' ') || (Char.IsNumber(_char) == true))
{
return false;
}
return true;
}
private void SaveWord(string word)
{
if (String.IsNullOrEmpty(word) == false)
{
outputList.Add(new SentenceSplitResult()
{
isAWord = true,
word = word
});
}
}
private void SaveANotWord(char _char)
{
outputList.Add(new SentenceSplitResult()
{
isAWord = false,
word = _char.ToString()
});
}