2010-05-06 2 views

ответ

2

Рассмотрите предложение как слово, содержащее пробелы, заканчивающееся периодом.

+5

Или восклицательный знак. Или вопросительный знак. Также обратите внимание, что могут быть пустые предложения - например, когда есть три восклицательных знака в строке. –

+5

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

+0

@Fyodor Soikin - вся пунктуация может быть проверена char.IsPunctuation и char.ToUpper для пунктуации вернет тот же символ. поэтому ваши заботы не нужны. – Andrey

3

В первом приближении вы могли бы рассматривать любую последовательность, такую ​​как [a-z]\.[ \n\t] как конец предложения.

+6

[.!?] \ S (? [A-z]) –

+1

@Joel: хорошее предложение - определенное улучшение. –

+0

@Joel Возможно, захват текста перед пунктуацией тоже? Это могло бы помочь отфильтровать общие аббревиатуры, такие как доктор, г-жа, миссис и т. Д. – statenjason

1

Существует код VB на this page, который не должен быть слишком сложным для преобразования в C#.

Однако последующие сообщения указывают на ошибки в алгоритме.

This blog имеет некоторые C# код, который претендует на работу:

Это автоматический заглавной буквы после каждой полной остановки (период), знак вопроса и восклицательный знак.

ОБНОВЛЕНИЕ 16 февраля 2010: Я переработал его, так что он не влияет на такие строки, как URL, и т.п.

12

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

Это, как говорится, вы можете получить «достаточно хорошее» решение, используя регулярные выражения для поиска слов после препинания в пунктах назначения, но вам нужно будет добавить несколько особых случаев. Может быть, проще обрабатывать строковый символ символом или слово за словом. Вам все равно придется обрабатывать все те же особые случаи, но это может быть проще, чем пытаться построить это в регулярное выражение.

Существует множество странных правил для грамматики и пунктуации. Любое решение, которое вы придумали, вероятно, не сможет учесть их всех. Некоторые вещи, чтобы рассмотреть следующие вопросы:

  • Приговоры могут закончиться с различными знаками препинания
  • Некоторых знаками препинания, которые заканчиваются предложения также могут быть использованы в середине предложения (например, аббревиатуры, такие как д-р Mr (.!?) например,
  • Предложения могут содержать вложенные предложения. Котировки могут представлять особую проблему (например, он сказал: «Это сложная проблема! Интересно, - подумал он, - если это можно решить».)
+8

Как вы получили так много авансов, фактически не давая ответа на вопрос? Я хочу знать имя твоего одеколона! –

+0

@jdk: Справедливая точка зрения, но дух моего ответа был больше того, что вы, вероятно, не можете сделать действительно хорошую работу во всех случаях. Я добавил немного больше советов для создания «достаточно хорошего» решения, которое может работать * больше всего времени. –

+0

Когда вы учитесь в школе градиента, вам нужно либо найти хорошее решение, либо доказать, что он NP-полностью. Ответ подобен доказательству того, что он NP-полный (он просто сдался). – earlNameless

0

мне нужно сделать что-то подобное, и это служило моим целям. Я передаю свои «предложения» как строки IEnumerable.

// Read sentences from text file (each sentence on a separate line) 
IEnumerable<string> lines = File.ReadLines(inputPath); 

// Call method below 
lines = CapitalizeFirstLetterOfEachWord(lines); 

private static IEnumerable<string> CapitalizeFirstLetterOfString(IEnumerable<string> inputLines) 
{ 
    // Will output: Lorem lipsum et 

    List<string> outputLines = new List<string>(); 

    TextInfo textInfo = new CultureInfo("en-US", false).TextInfo; 

    foreach (string line in inputLines) 
    { 
    string lineLowerCase = textInfo.ToLower(line); 
    string[] lineSplit = lineLowerCase.Split(' '); 
    bool first = true; 

    for (int i = 0; i < lineSplit.Length; i++) 
    { 
     if (first) 
     { 
     lineSplit[0] = textInfo.ToTitleCase(lineSplit[0]); 
     first = false; 
     } 
    } 

    outputLines.Add(string.Join(" ", lineSplit)); 
    } 

    return outputLines; 

}

0

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

Вот мой метод расширения капитализировать предложения:

public static string CapitalizeSentences(this string Input) 
    { 
     if (String.IsNullOrEmpty(Input)) 
      return Input; 

     if (Input.Length == 1) 
      return Input.ToUpper(); 


     Input = Regex.Replace(Input, @"\s+", " "); 

     Input = Input.Trim().ToLower(); 
     Input = Char.ToUpper(Input[0]) + Input.Substring(1); 


     var objDelimiters = new string[] { ". ", "! ", "? " }; 
     foreach (var objDelimiter in objDelimiters) 
     { 
      var varDelimiterLength = objDelimiter.Length; 

      var varIndexStart = Input.IndexOf(objDelimiter, 0); 
      while (varIndexStart > -1) 
      { 
       Input = Input.Substring(0, varIndexStart + varDelimiterLength) + (Input[varIndexStart + varDelimiterLength]).ToString().ToUpper() + Input.Substring((varIndexStart + varDelimiterLength) + 1); 

       varIndexStart = Input.IndexOf(objDelimiter, varIndexStart + 1); 
      } 
     } 


     return Input; 
    } 


Подробнее об алгоритме:
Этот простой алгоритм начинает удаление все двойные пробелы. Затем он использует первый символ строки. затем выполните поиск каждого разделителя. Когда вы найдете его, загладьте самый следующий символ.
Я упростил добавление/удаление или редактирование разделителей, поэтому вы можете многое изменить, как работает код с небольшими изменениями. Он не проверяет, выходят ли подстроки из длины строки, потому что разделители заканчиваются пробелами, а алгоритм начинается с «Trim()», поэтому каждый разделитель, если он найден в строке, будет сопровождаться другим символом.

Важно:
Вы не указали, что были именно ваши потребности. Я имею в виду, это корректор грамматики, это просто для того, чтобы прикрыть текст и т. Д. Итак, важно учитывать, что мой алгоритм - это всего лишь , который идеально подходит для моих потребностей, которые могут отличаться от ваших.
* Этот алгоритм был создан для форматирования «Product Description», который не нормализуется (почти всегда полностью закрыт) в приятном формате для пользователя (Чтобы быть более конкретным, мне нужно показать красивую и «меньшую», текст для пользователя. Итак, все символы в Upper Case просто противоположны тому, что я хочу). Таким образом, он не был создан, чтобы быть грамматически совершенным.
* Также есть некоторые исключения, в которых персонаж не будет в верхнем регистре, потому что плохое форматирование.
* Я выбираю включать пробелы в разделитель, поэтому «http://www.stackoverflow.com» не станет «http://www.Stackoverflow.Com». С другой стороны, такие предложения, как «коробка blue.it на полу», станут «Коробка синяя. На полу», а не «Коробка синяя. Она находится на полу»
* В аббревиатурах дела он будет использоваться, но опять же, это не проблема, потому что мои потребности просто показывают описание продукта (где грамматика не критична). И в аббревиатурах, таких как г-н или д-р, первый символ - это имя, поэтому он идеально подходит для капитализации.

Если вам или кому-то еще нужен более точный алгоритм, я буду рад его улучшить.

Надеюсь, что я помогу кому-нибудь!

0

Однако вы можете сделать класс или метод для преобразования каждого текста в TitleCase. Вот пример, который вам нужно просто вызвать метод.

public static string ToTitleCase(string strX) 
    { 
     string[] aryWords = strX.Trim().Split(' '); 

     List<string> lstLetters = new List<string>(); 
     List<string> lstWords = new List<string>(); 

     foreach (string strWord in aryWords) 
     { 
      int iLCount = 0; 
      foreach (char chrLetter in strWord.Trim()) 
      { 
       if (iLCount == 0) 
       { 
        lstLetters.Add(chrLetter.ToString().ToUpper()); 
       } 
       else 
       { 
        lstLetters.Add(chrLetter.ToString().ToLower()); 
       } 
       iLCount++; 
      } 
      lstWords.Add(string.Join("", lstLetters)); 
      lstLetters.Clear(); 
     } 

     string strNewString = string.Join(" ", lstWords); 

     return strNewString; 
    } 
Смежные вопросы