32

我正在寻找一个函数来将大写的文本字符串转换为 SentenceCase。我能找到的所有示例都将文本转换为 TitleCase。

一般意义上的句子大小写描述了在句子中使用大写的方式。句子大小写还描述了英语句子的标准大写,即句子的第一个字母大写,其余字母小写(除非出于特定原因需要大写,例如专有名词、首字母缩略词等)。

谁能指出我的 SentenceCase 脚本或函数的方向?

4

8 回答 8

47

.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."

这可以通过多种不同的方式进行改进,以更好地匹配更广泛的句型(不仅仅是那些以字母+句号结尾的句型)。

于 2010-06-29T14:09:40.600 回答
11

这对我有用。

/// <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);
}
于 2010-06-29T14:11:47.503 回答
5

有一个内置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

于 2013-04-04T11:23:42.763 回答
3

如果您想判断一个包含标点符号的字符串,而不仅仅是句点:

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());
于 2014-10-16T19:02:42.373 回答
2

如果你输入的字符串不是一个句子,而是很多个句子,这将成为一个非常困难的问题。

正则表达式将被证明是一个非常宝贵的工具,但是 (1) 你必须非常了解它们才能有效,并且 (2) 它们可能无法完全靠自己完成这项工作。

考虑这句话

“谁在 1 号,”史密斯先生——他没有笑——回答道。

这句话不是以字母开头,它有一个数字,各种标点符号,一个专有名称,.中间有一个。

复杂性是巨大的,这是一句话。

使用 RegEx 时最重要的事情之一就是“了解您的数据”。如果您知道要处理的句子类型的广度,您的任务将更易于管理。

无论如何,您将不得不玩弄您的实施,直到您对结果感到满意为止。我建议使用一些示例输入编写一些自动化测试——当你在你的实现上工作时,你可以定期运行测试,看看你在哪里接近了,在哪里你仍然错过了标记。

于 2010-06-29T14:42:33.083 回答
1

这就是我使用的(VB.NET)。它适用于大多数情况,包括:

  • 多个句子
  • 以空格开头和结尾的句子
  • 以 AZ 以外的字符开头的句子。例如,它适用于:“如果你想要 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
    

但至于专有名词和首字母缩略词,嗯……在英语中总会出现标点符号不那么简单的情况。例如,此脚本不会检测到省略号(“...”)或缩写(例如:“琼斯先生住在 Chris 家附近的 Magnolia Blvd.”)。

为了彻底解决这个问题,您需要为该语言制作所有可能的缩写/标点符号的字典,并保持字典是最新的!考虑到这一点后,大多数人都会对折衷感到满意,否则只需使用 Microsoft Word。

于 2012-05-04T04:44:43.077 回答
1

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)
于 2019-08-22T19:41:56.397 回答
0
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();
}
于 2016-09-14T08:34:03.747 回答