我正在寻找一个函数来将大写的文本字符串转换为 SentenceCase。我能找到的所有示例都将文本转换为 TitleCase。
一般意义上的句子大小写描述了在句子中使用大写的方式。句子大小写还描述了英语句子的标准大写,即句子的第一个字母大写,其余字母小写(除非出于特定原因需要大写,例如专有名词、首字母缩略词等)。
谁能指出我的 SentenceCase 脚本或函数的方向?
我正在寻找一个函数来将大写的文本字符串转换为 SentenceCase。我能找到的所有示例都将文本转换为 TitleCase。
一般意义上的句子大小写描述了在句子中使用大写的方式。句子大小写还描述了英语句子的标准大写,即句子的第一个字母大写,其余字母小写(除非出于特定原因需要大写,例如专有名词、首字母缩略词等)。
谁能指出我的 SentenceCase 脚本或函数的方向?
.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."
这可以通过多种不同的方式进行改进,以更好地匹配更广泛的句型(不仅仅是那些以字母+句号结尾的句型)。
这对我有用。
/// <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);
}
有一个内置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
如果您想判断一个包含标点符号的字符串,而不仅仅是句点:
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());
如果你输入的字符串不是一个句子,而是很多个句子,这将成为一个非常困难的问题。
正则表达式将被证明是一个非常宝贵的工具,但是 (1) 你必须非常了解它们才能有效,并且 (2) 它们可能无法完全靠自己完成这项工作。
考虑这句话
“谁在 1 号,”史密斯先生——他没有笑——回答道。
这句话不是以字母开头,它有一个数字,各种标点符号,一个专有名称,.
中间有一个。
复杂性是巨大的,这是一句话。
使用 RegEx 时最重要的事情之一就是“了解您的数据”。如果您知道要处理的句子类型的广度,您的任务将更易于管理。
无论如何,您将不得不玩弄您的实施,直到您对结果感到满意为止。我建议使用一些示例输入编写一些自动化测试——当你在你的实现上工作时,你可以定期运行测试,看看你在哪里接近了,在哪里你仍然错过了标记。
这就是我使用的(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。
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)
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();
}