c# - 使用 C# 格式化字符串中的句子

我有一个包含多个句子的字符串。如何将每个句子中第一个单词的第一个字母大写。类似于 word 中的段落格式。

eg ."这是一些代码。代码是用 C# 编写的。" 输出必须是“这是一些代码。代码在 C# 中”。

一种方法是根据 '.' 拆分字符串。然后将第一个字母大写,然后重新加入。

有没有更好的解决方案?

最佳答案

在我看来,当涉及到潜在的复杂的基于规则的字符串匹配和替换时——你不能比基于正则表达式的解决方案更好(尽管它们很难阅读!)。在我看来,这提供了最好的性能和内存效率——你会惊讶于它的速度有多快。

我会使用 Regex.Replace overload that accepts an input string, regex pattern and a MatchEvaluator delegate . MatchEvaluator 是一个接受 Match 对象作为输入并返回字符串替换的函数。

代码如下:

public static string Capitalise(string input)
{
  //now the first character
  return Regex.Replace(input, @"(?<=(^|[.;:])\s*)[a-z]",
    (match) => { return match.Value.ToUpper(); });
}

正则表达式使用 (?[.;:] 位中,您可以添加所需的额外部分(例如,[.;:?."] 以添加 ? 和 "字符。

这也意味着,您的 MatchEvaluator 不必进行任何不必要的字符串连接(出于性能原因,您希望避免这种情况)。

从性能的角度来看,其他回答者之一提到的有关使用 RegexOptions.Compiled 的所有其他内容也与此相关。不过,静态 Regex.Replace 方法确实提供了非常相似的性能优势(只是额外的字典查找)。

就像我说的 - 如果这里的任何其他非正则表达式解决方案能够更好地工作并且速度一样快,我会感到惊讶。

编辑

已将此解决方案与 Ahmad 的解决方案相提并论,因为他非常正确地指出,环顾四周可能不如按照自己的方式进行。

这是我做的粗略基准:

public string LowerCaseLipsum
{
  get
  {
    //went to lipsum.com and generated 10 paragraphs of lipsum
    //which I then initialised into the backing field with @"[lipsumtext]".ToLower()
    return _lowerCaseLipsum;
  }
 }
 [TestMethod]
 public void CapitaliseAhmadsWay()
 {
   List<string> results = new List<string>();
   DateTime start = DateTime.Now;
   Regex r = new Regex(@"(^|\p{P}\s+)(\w+)", RegexOptions.Compiled);
   for (int f = 0; f < 1000; f++)
   {
     results.Add(r.Replace(LowerCaseLipsum, m => m.Groups[1].Value
                      + m.Groups[2].Value.Substring(0, 1).ToUpper()
                           + m.Groups[2].Value.Substring(1)));
   }
   TimeSpan duration = DateTime.Now - start;
   Console.WriteLine("Operation took {0} seconds", duration.TotalSeconds);
 }

 [TestMethod]
 public void CapitaliseLookAroundWay()
 {
   List<string> results = new List<string>();
   DateTime start = DateTime.Now;
   Regex r = new Regex(@"(?<=(^|[.;:])\s*)[a-z]", RegexOptions.Compiled);
   for (int f = 0; f < 1000; f++)
   {
     results.Add(r.Replace(LowerCaseLipsum, m => m.Value.ToUpper()));
   }
   TimeSpan duration = DateTime.Now - start;
   Console.WriteLine("Operation took {0} seconds", duration.TotalSeconds);
 }

在发布版本中,我的解决方案比 Ahmad 的解决方案快约 12%(1.48 秒而不是 1.68 秒)。

然而,有趣的是,如果通过静态 Regex.Replace 方法完成,两者都慢了大约 80%,而且我的解决方案比 Ahmad 的慢。

https://stackoverflow.com/questions/2135863/

相关文章:

python - 从 lxml.objectify.ObjectifiedElement 中剥离 p

c++ - 在不改变缩进的情况下重新格式化 C++ 大括号?

javascript - 有没有办法使用 Moment.js 解析相对日期?

eclipse - 在 Eclipse 格式化程序中的花括号上强制 "same line"

javascript - 谷歌图表显示金钱而​​不是百分比

java - 将 4 位军用时间转换为标准 12 小时时间格式

django - 如何格式化 django 评论的表单字段?

c# - 将规范化的电话号码转换为用户友好的版本

formatting - 是否可以使 PHP 错误看起来更好? Stack 可以在单独的行上跟踪输出

.net - 如何将 NLog 的文件名设置为进程开始日期?