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

标签 c# string formatting paragraph text-segmentation

我有一个包含多个句子的字符串。如何将每个句子中第一个单词的第一个字母大写。类似于 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(); });
}

正则表达式使用 (?<=) 构造(零宽度正向后视)将捕获仅限于字符串开头前面的 a-z 字符或您想要的标点符号。在 [.;:] 位中,您可以添加所需的额外部分(例如,[.;:?."] 以添加 ? 和 "字符。

这也意味着,您的 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 的慢。

关于c# - 使用 C# 格式化字符串中的句子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2135863/

相关文章:

r - 如何在 R Shiny 中对数据帧进行条件格式设置?

CSS 变换和过渡

c# - 如何立即写入文件?

c# - 如何设置几个visual C#项目的输出路径

C# 将字符的 x 次出现附加到字符串

string - 如果不是空字符串,则 Excel 总和

java - 为什么 Spring Boot DefaultFormattingConversionService 被创建但没有被引用?

c# - 对 C# 异步方法结果进行操作

c# - 查找未处理的异常 - .NET

sql - 在 SQL 中搜索行以查找无效字符