Подтвердить что ты не робот

Метод .NET для преобразования строки в случай предложения

Я ищу функцию для преобразования строки текста, находящейся в UpperCase, в SentenceCase. Все примеры, которые я могу найти, превращают текст в TitleCase.

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

Может ли кто-нибудь указать мне в сторону script или функцию для SentenceCase?

4b9b3361

Ответ 1

В .NET нет ничего встроенного в .NET. Однако это один из тех случаев, когда обработка регулярных выражений может работать хорошо. Я бы начал сначала преобразовать всю строку в нижний регистр, а затем, в первом приближении, вы можете использовать регулярное выражение для поиска всех последовательностей, таких как [a-z]\.\s+(.), и использовать ToUpper() для преобразования захваченной группы в верхний регистр. Класс RegEx имеет перегруженный метод Replace(), который принимает делегат MatchEvaluator, который позволяет вам определить, как заменить согласованное значение.

Вот пример кода этого на работе:

var sourcestring = "THIS IS A GROUP. OF CAPITALIZED. LETTERS.";
// start by converting entire string to lower case
var lowerCase = sourcestring.ToLower();
// matches the first sentence of a string, as well as subsequent sentences
var r = new Regex(@"(^[a-z])|\.\s+(.)", RegexOptions.ExplicitCapture);
// MatchEvaluator delegate defines replacement of setence starts to uppercase
var result = r.Replace(lowerCase, s => s.Value.ToUpper());

// result is: "This is a group. Of uncapitalized. Letters."

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

Ответ 2

Это работает для меня.

/// <summary>
/// Converts a string to sentence case.
/// </summary>
/// <param name="input">The string to convert.</param>
/// <returns>A string</returns>
public static string SentenceCase(string input)
{
    if (input.Length < 1)
        return input;

    string sentence = input.ToLower();
    return sentence[0].ToString().ToUpper() +
       sentence.Substring(1);
}

Ответ 3

Существует встроенная функция ToTitleCase(), которая будет расширена для поддержки нескольких культур в будущем.

Пример из MSDN:

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      string[] values = { "a tale of two cities", "gROWL to the rescue",
                          "inside the US government", "sports and MLB baseball",
                          "The Return of Sherlock Holmes", "UNICEF and children"};

      TextInfo ti = CultureInfo.CurrentCulture.TextInfo;
      foreach (var value in values)
         Console.WriteLine("{0} --> {1}", value, ti.ToTitleCase(value));
   }
}
// The example displays the following output:
//    a tale of two cities --> A Tale Of Two Cities
//    gROWL to the rescue --> Growl To The Rescue
//    inside the US government --> Inside The US Government
//    sports and MLB baseball --> Sports And MLB Baseball
//    The Return of Sherlock Holmes --> The Return Of Sherlock Holmes
//    UNICEF and children --> UNICEF And Children

Хотя это, как правило, полезно, оно имеет ряд важных ограничений:

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

... метод ToTitleCase обеспечивает произвольное поведение обсадной колонны что не обязательно лингвистически правильно. Лингвистически Для правильного решения потребуются дополнительные правила, а действующий Алгоритм несколько проще и быстрее. Мы оставляем за собой право сделать этот API медленнее в будущем.

Источник: http://msdn.microsoft.com/en-us/library/system.globalization.textinfo.totitlecase.aspx

Ответ 5

Если ваша строка ввода не является предложением, а множеством предложений, это становится очень сложной проблемой.

Регулярные выражения окажутся неоценимым инструментом, но (1) вам нужно будет хорошо их понять, чтобы быть эффективными, и (2) они могут не выполнять свою работу полностью самостоятельно.

Рассмотрим это предложение

"Кто на первом месте, - ответил мистер Смит, который не смеялся, - ответил.

Это предложение не начинается с буквы, оно имеет цифру, различную пунктуацию, собственное имя и . в середине.

Сложности огромны, и это одно предложение.

Одна из самых важных вещей при использовании RegEx - "знать ваши данные". Если вы знаете широту типов предложений, с которыми будете иметь дело, ваша задача будет более управляемой.

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

Ответ 6

Если вы хотите придать случаю строку, содержащую знаки препинания, отличные от периодов:

string input = "THIS IS YELLING! WHY ARE WE YELLING? BECAUSE WE CAN. THAT IS ALL.";
var sentenceRegex = new Regex(@"(^[a-z])|[?!.:,;]\s+(.)", RegexOptions.ExplicitCapture);
input = sentenceRegex.Replace(input.ToLower(), s => s.Value.ToUpper());

Ответ 7

Это то, что я использую (VB.NET). Он работает в большинстве ситуациях, в том числе:

  • несколько предложений
  • предложения, начинающиеся и заканчивающиеся пробелами
  • предложения, начинающиеся с символов, отличных от A-Z. Например, он будет работать для: "если вы хотите $100,00, то просто спросите меня".

    <Extension()>
    Public Function ToSentanceCase(ByVal s As String) As String
        ' Written by Jason. Inspired from: http://www.access-programmers.co.uk/forums/showthread.php?t=147680
    
        Dim SplitSentence() As String = s.Split(".")
    
        For i = 0 To SplitSentence.Count - 1
            Dim st = SplitSentence(i)
    
            If st.Trim = "" Or st.Trim.Count = 1 Then Continue For ' ignore empty sentences or sentences with only 1 character.
    
            ' skip past characters that are not A-Z, 0-9 (ASCII) at start of sentence.
            Dim y As Integer = 1
            Do Until y > st.Count
                If (Asc(Mid(st, y, 1)) >= 65 And Asc(Mid(st, y, 1)) <= 90) Or _
                      (Asc(Mid(st, y, 1)) >= 97 And Asc(Mid(st, y, 1)) <= 122) Or _
                     (Asc(Mid(st, y, 1)) >= 48 And Asc(Mid(st, y, 1)) <= 57) Then
                    GoTo Process
                Else
                    Dim w = Asc(Mid(st, y, 1))
                    y += 1
                End If
            Loop
            Continue For
    
    Process:
            Dim sStart As String = ""
            If y > 1 Then sStart = Left(st, 0 + (y - 1))
    
            Dim sMid As String = UCase(st(y - 1)) ' capitalise the first non-space character in sentence.
    
            Dim sEnd As String = Mid(st, y + 1, st.Length)
    
            SplitSentence(i) = sStart & sMid & sEnd
    
        Next
    
        ' rejoin sentances back together:
        Dim concat As String = ""
        For Each st As String In SplitSentence
            concat &= st & "."
        Next
    
        concat = concat.TrimEnd(1)
    
        Return concat
    
    End Function
    

Но что касается собственных существительных и акронимов, то... на английском языке всегда будут ситуации, где пунктуация не так проста. Например, этот script не будет обнаруживать многоточие ( "..." ) или аббревиатуры (например: "Мистер Джонс жил на бульваре Магнолия возле дома Криса" ).

Чтобы полностью решить проблему, вам понадобится создать словарь всех возможных сокращений/знаков препинания для языка и сохранить словарь в актуальном состоянии! Рассмотрев это, большинство из них будут довольны компромиссом, иначе просто используйте Microsoft Word.

Ответ 8

Решение в F #:

open System

let proper (x : string) =
    x.Split(' ')
    |> Array.filter ((<>) "")
    |> Array.map (fun t ->
        let head = Seq.head t |> Char.ToUpper |> string
        let tail = Seq.tail t |> Seq.map (Char.ToLower >> string)
        Seq.append [head] tail
        |> Seq.reduce (fun acc elem -> acc + elem))
    |> Array.reduce (fun acc elem -> acc + " " + elem)

Ответ 9

public string GetSentenceCase(string ReqdString) {
    string StrInSentCase = "";
    for (int j = 0; j < ReqdString.Length; j++) {
        if (j == 0) {
           StrInSentCase = ReqdString.ToString().Substring(j, 1).ToUpper();
        }
        else {
            StrInSentCase = StrInSentCase + ReqdString.ToString().Substring(j, 1).ToLower();
        }
    }
    return StrInSentCase.ToString();
}