【问题标题】:Capitalizing words in a string using C#使用 C# 将字符串中的单词大写
【发布时间】:2010-11-30 15:45:30
【问题描述】:

我需要一个字符串,并将其中的单词大写。某些单词(“in”、“at”等)没有大写,如果遇到则更改为小写。第一个单词应始终大写。像“McFly”这样的姓氏不在当前范围内,所以同样的规则将适用于他们——只有首字母大写。

例如:“of mouse and men By CNN”应更改为“Of Mice and Men by CNN”。 (因此 ToTitleString 在这里不起作用。)

最好的方法是什么?

我想用空格分割字符串,检查每个单词,如有必要,更改它,然后将它连接到前一个单词,等等。 这似乎很天真,我想知道是否有更好的方法来做到这一点。我正在使用 .NET 3.5。

【问题讨论】:

  • 程序应该如何理解CNN应该全部大写?
  • @Chris:我认为他的意思是 ToTitleCase ...?请参阅此处msdn.microsoft.com/en-us/library/… 和“备注”以了解为什么它不适用。
  • @Øyvind:该程序可能会尊重现有的大写字母,并且只会将大小写更改为大写,而不是小写。示例中唯一不起作用的地方是“By”变成“by”的地方。当遇到全小写的“by”时,我认为应该将其匹配到字典中以保留为小写,但是当遇到“By”时,我真的认为应该这样保留,因为我们无法区分它来自名为“By”的潜在城市(或其他城市)。
  • 看起来 ToTitleCase 可以通过一些小的调整来做到这一点,假设你只想要英语而不想要其他文化。
  • How to Capitalize names的可能重复

标签: c# string capitalization


【解决方案1】:

使用

Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase("of mice and men By CNN");

转换为正确的大小写,然后您可以循环遍历您提到的关键字。

【讨论】:

  • 这很接近,但是如果您查看 OP 的示例,则“And”不应大写。但这可能是算法的第一步。是否进行 ToTitleCase 转换并根据字典查找特殊情况的单词并将它们恢复为小写?
【解决方案2】:

根据您计划进行大写的频率,我会采用幼稚的方法。您可以使用正则表达式来做到这一点,但您不希望某些单词大写这一事实使得这有点棘手。

您可以使用正则表达式通过两遍来做到这一点:

var result = Regex.Replace("of mice and men isn't By CNN", @"\b(\w)", m => m.Value.ToUpper());
result = Regex.Replace(result, @"(\s(of|in|by|and)|\'[st])\b", m => m.Value.ToLower(), RegexOptions.IgnoreCase);

这会输出Of Mice and Men Isn't by CNN

第一个表达式将单词边界上的每个字母大写,第二个表达式将匹配列表中被空格包围的所有单词小写。

这种方法的缺点是您使用的是正则表达式(现在您遇到了两个问题),并且您需要使排除的单词列表保持最新。我的 regex-fu 不够好,无法在一个表达式中完成,但它可能是可能的。

【讨论】:

  • 这有一个小错误。对于像“Tom's thing”这样的字符串,结果是“Tom'S Thing”。
【解决方案3】:

另一个问题的答案,How to Capitalize names -

CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
TextInfo textInfo = cultureInfo.TextInfo;

Console.WriteLine(textInfo.ToTitleCase(title));
Console.WriteLine(textInfo.ToLower(title));
Console.WriteLine(textInfo.ToUpper(title));

【讨论】:

    【解决方案4】:

    首先使用ToTitleCase(),然后保留一个适用词的列表,然后Replace返回这些适用词的全小写版本(前提是该列表很小)。

    适用的单词列表可以保存在字典中,并且可以非常有效地循环,替换为 .ToLower() 等效项。

    【讨论】:

    • 我知道答案是旧的,但 ToTitleCase() 在 .NET Windows 应用商店中不再存在。您将只需要依赖 ToUpper() 并且可能需要一些 Regex 来用于未来的应用程序。
    • 感谢您的更新,非常感谢。
    【解决方案5】:

    试试这样的:

    public static string TitleCase(string input, params string[] dontCapitalize) {
       var split = input.Split(' ');
       for(int i = 0; i < split.Length; i++)
            split[i] = i == 0 
              ? CapitalizeWord(split[i]) 
              : dontCapitalize.Contains(split[i])
                 ? split[i]
                 : CapitalizeWord(split[i]);
       return string.Join(" ", split);
    }
    public static string CapitalizeWord(string word)
    {
        return char.ToUpper(word[0]) + word.Substring(1);
    }
    

    如果您需要处理复杂的姓氏,您可以稍后更新CapitalizeWord 方法。 将这些方法添加到一个类中并像这样使用它:

    SomeClass.TitleCase("a test is a sentence", "is", "a"); // returns "A Test is a Sentence"
    

    【讨论】:

      【解决方案6】:

      jonnii's answer略有改进:

      var result = Regex.Replace(s.Trim(), @"\b(\w)", m => m.Value.ToUpper());
      result = Regex.Replace(result, @"\s(of|in|by|and)\s", m => m.Value.ToLower(), RegexOptions.IgnoreCase);
      result = result.Replace("'S", "'s");
      

      【讨论】:

        【解决方案7】:

        您可以拥有一个包含您想忽略的单词的字典,将句子拆分为短语 (.split(' ')) 并为每个短语检查该短语是否存在于字典中,如果不存在,则大写第一个字符,然后将字符串添加到字符串缓冲区。如果您当前正在处理的短语在字典中,只需将其添加到字符串缓冲区即可。

        【讨论】:

          【解决方案8】:

          处理简单情况的非聪明方法:

          var s = "of mice and men By CNN";
          var sa = s.Split(' ');
          for (var i = 0; i < sa.Length; i++)
              sa[i] = sa[i].Substring(0, 1).ToUpper() + sa[i].Substring(1);
          var sout = string.Join(" ", sa);
          Console.WriteLine(sout);
          

          【讨论】:

            【解决方案9】:

            最简单明显的解决方案(对于英语句子)是:

            • "sentence".Split(" ")关于空格字符的句子
            • 遍历每个项目
            • 每个项目的首字母大写 - item[i][0].ToUpper(),
            • 重新合并成一个加入空格的字符串。
            • 用“.”重复这个过程和 "," 使用该新字符串。

            【讨论】:

              【解决方案10】:

              您应该像您描述的那样创建自己的函数。

              【讨论】:

                猜你喜欢
                • 2013-02-28
                • 1970-01-01
                • 2016-09-06
                • 2018-08-06
                • 1970-01-01
                • 2016-02-15
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多