【问题标题】:How to capitalize the first character of each word, or the first character of a whole string, with C#?如何使用 C# 将每个单词的第一个字符或整个字符串的第一个字符大写?
【发布时间】:2010-10-29 02:59:27
【问题描述】:

我可以编写自己的算法来做到这一点,但我觉得 C# 中应该有与 ruby's humanize 等价的东西。

我用谷歌搜索了它,但只找到了人性化日期的方法。

例子:

  • 一种将“Lorem Lipsum Et”变成“Lorem Lipsum et”的方法
  • 一种将“Lorem Lipsum et”转变为“Lorem Lipsum Et”的方法

【问题讨论】:

  • 出于某种原因我喜欢说 Lorem Lipsum ^^
  • 总是有正则表达式!字符串 strToCap = strSource.ToLower();正则表达式 rCapitalize = new Regex("(? { return m.Value.ToUpper(); }); ...但是你会有两个问题。 :)
  • 由于接受的答案链接到与原始问题要求相反的代码,我编辑了问题以询问两个方向,希望这个问题不会完全让未来偶然发现它的用户感到困惑。
  • 虽然 OP 的示例字符串可能没有提到,但很多人正在失去标题大小写和大写之间的区别。标题大小写不将常用词大写,所以即使它在上面工作,它也是错误的解决方案。狗快与狗快。后者是大写。

标签: c# string humanize


【解决方案1】:

正如 @miguel's answer 的 cmets 中所讨论的,您可以使用自 .NET 1.1 起就可用的 TextInfo.ToTitleCase。这是与您的示例相对应的一些代码:

string lipsum1 = "Lorem lipsum et";

// Creates a TextInfo based on the "en-US" culture.
TextInfo textInfo = new CultureInfo("en-US",false).TextInfo;

// Changes a string to titlecase.
Console.WriteLine("\"{0}\" to titlecase: {1}", 
                  lipsum1, 
                  textInfo.ToTitleCase( lipsum1 )); 

// Will output: "Lorem lipsum et" to titlecase: Lorem Lipsum Et

它将忽略所有大写的内容,例如“LOREM LIPSUM ET”,因为它会处理首字母缩略词在文本中的情况,以便“IEEE”(电气和电子工程师协会)不会变成“ieee” " 或 "ieee"。

但是,如果您只想将第一个字符大写,您可以使用超过 here... 的解决方案,或者您可以拆分字符串并将列表中的第一个字符大写:

string lipsum2 = "Lorem Lipsum Et";

string lipsum2lower = textInfo.ToLower(lipsum2);

string[] lipsum2split = lipsum2lower.Split(' ');

bool first = true;

foreach (string s in lipsum2split)
{
    if (first)
    {
        Console.Write("{0} ", textInfo.ToTitleCase(s));
        first = false;
    }
    else
    {
        Console.Write("{0} ", s);
    }
}

// Will output: Lorem lipsum et 

【讨论】:

  • 怎么会有更多的人不知道这件事。这是出色的内置方法,谢谢
  • 哈哈 3 年后,NAMBLA 仍然让我发笑,哦,为 ToTitleCase() +1
  • 发现问题的 ToTitleCase 1st 将变为 1St。
  • 发现 ToTitleCase 的第二个问题 -  会变成 &Nbsp;
  • @Brain2000 如果你在使用ToTitleCase之前知道there are HTML entities in the string then you should let your code handle that
【解决方案2】:

我使用自定义扩展方法实现了同样的效果。对于第一个子字符串的第一个字母,使用方法yourString.ToFirstLetterUpper()。对于不包括文章和一些命题的每个子字符串的首字母,使用方法yourString.ToAllFirstLetterInUpper()。下面是一个控制台程序:

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("this is my string".ToAllFirstLetterInUpper());
            Console.WriteLine("uniVersity of lonDon".ToAllFirstLetterInUpper());
        }
    }

    public static class StringExtension
    {
        public static string ToAllFirstLetterInUpper(this string str)
        {
            var array = str.Split(" ");

            for (int i = 0; i < array.Length; i++)
            {
                if (array[i] == "" || array[i] == " " || listOfArticles_Prepositions().Contains(array[i])) continue;
                array[i] = array[i].ToFirstLetterUpper();
            }
            return string.Join(" ", array);
        }

        private static string ToFirstLetterUpper(this string str)
        {
            return str?.First().ToString().ToUpper() + str?.Substring(1).ToLower();
        }

        private static string[] listOfArticles_Prepositions()
        {
            return new[]
            {
                "in","on","to","of","and","or","for","a","an","is"
            };
        }
    }

输出

This is My String
University of London
Process finished with exit code 0.

【讨论】:

    【解决方案3】:

    所有示例似乎都使其他字符首先降低,这不是我需要的。

    customerName = CustomerName

    this is an example = This Is An Example

    public static string ToUpperEveryWord(this string s)
    {
        // Check for empty string.  
        if (string.IsNullOrEmpty(s))
        {
            return string.Empty;
        }
    
        var words = s.Split(' ');
    
        var t = "";
        foreach (var word in words)
        {
            t += char.ToUpper(word[0]) + word.Substring(1) + ' ';
        }
        return t.Trim();
    }
    

    【讨论】:

    • 如果你不想使用 .TextInfo.ToTitleCase 这是正确的解决方案
    【解决方案4】:

    还有另一个优雅的解决方案:

    在你的项目的 static 类中定义函数 ToTitleCase

    using System.Globalization;
    
    public static string ToTitleCase(this string title)
    {
        return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(title.ToLower()); 
    }
    

    然后在项目的任何地方使用它,就像字符串扩展一样:

    "have a good day !".ToTitleCase() // "Have A Good Day !"
    

    【讨论】:

    • 在传递给ToTitleCase之前,您还应该使用title.ToLower()。否则大写字母不会被替换。
    【解决方案5】:

    使用正则表达式看起来更干净:

    string s = "the quick brown fox jumps over the lazy dog";
    s = Regex.Replace(s, @"(^\w)|(\s\w)", m => m.Value.ToUpper());
    

    【讨论】:

    • 展开答案:string s = "tThe Quick Brown fOx juMps over the LAzy doG"; s = Regex.Replace(s.ToLower(), @"(^\w)|(\s\w)", m => m.Value.ToUpper());
    • 这一行非正则表达式也适用:s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(value.ToLower());
    • @Roberto - "hEm" -> 正则表达式 = "HEm"; "hEm" -> TitleCase = "Hem"
    • 我觉得这个比较简单Regex.Replace(s, @"\b([a-z])", m =&gt; m.Value.ToUpper())
    【解决方案6】:

    CSS 技术没问题,但只会改变字符串在浏览器中的呈现方式。更好的方法是在发送到浏览器之前使文本本身大写。

    上面的大多数实现都是可以的,但是它们都没有解决如果你有混合大小写的单词需要保留,或者如果你想使用真正的标题大小写会发生什么的问题,例如:

    “去美国读博士课程的地方”

    “IRS 表格 UB40a”

    还使用 CultureInfo.CurrentCulture.TextInfo.ToTitleCase(string) 保留大写单词,如 “sports and MLB棒球”变成了“Sports And MLB Baseball”,但如果整个字符串都是大写的,那么这会导致问题。

    所以我整理了一个简单的函数,通过将它们包含在 specialCases 和 lowerCases 字符串中,您可以保留大写单词和混合大小写单词,并使小单词小写(如果它们不在短语的开头和结尾)数组:

    public static string TitleCase(string value) {
            string titleString = ""; // destination string, this will be returned by function
            if (!String.IsNullOrEmpty(value)) {
                string[] lowerCases = new string[12] { "of", "the", "in", "a", "an", "to", "and", "at", "from", "by", "on", "or"}; // list of lower case words that should only be capitalised at start and end of title
                string[] specialCases = new string[7] { "UK", "USA", "IRS", "UCLA", "PHd", "UB40a", "MSc" }; // list of words that need capitalisation preserved at any point in title
                string[] words = value.ToLower().Split(' ');
                bool wordAdded = false; // flag to confirm whether this word appears in special case list
                int counter = 1;
                foreach (string s in words) {
    
                    // check if word appears in lower case list
                    foreach (string lcWord in lowerCases) {
                        if (s.ToLower() == lcWord) {
                            // if lower case word is the first or last word of the title then it still needs capital so skip this bit.
                            if (counter == 0 || counter == words.Length) { break; };
                            titleString += lcWord;
                            wordAdded = true;
                            break;
                        }
                    }
    
                    // check if word appears in special case list
                    foreach (string scWord in specialCases) {
                        if (s.ToUpper() == scWord.ToUpper()) {
                            titleString += scWord;
                            wordAdded = true;
                            break;
                        }
                    }
    
                    if (!wordAdded) { // word does not appear in special cases or lower cases, so capitalise first letter and add to destination string
                        titleString += char.ToUpper(s[0]) + s.Substring(1).ToLower();
                    }
                    wordAdded = false;
    
                    if (counter < words.Length) {
                        titleString += " "; //dont forget to add spaces back in again!
                    }
                    counter++;
                }
            }
            return titleString;
        }
    

    这只是一种快速简单的方法 - 如果您想花更多时间在上面,可能会有所改进。

    如果您想保留“a”和“of”等较小单词的大写,则只需将它们从特殊情况字符串数组中删除即可。不同的组织对大小写有不同的规定。

    您可以在此站点上看到此代码的示例:Egg Donation London - 此站点通过解析 URL 自动在页面顶部创建面包屑路径,例如“/services/uk-egg-bank/introduction” - 然后路径中的每个文件夹名称都将连字符替换为空格并将文件夹名称大写,因此 uk-egg-bank 变为 UK Egg Bank。 (保留大写“UK”)

    此代码的扩展可能是在共享文本文件、数据库表或 Web 服务中具有首字母缩略词和大写/小写单词的查找表,以便可以从一个位置维护混合大小写单词列表并应用到许多依赖该函数的不同应用程序。

    【讨论】:

      【解决方案7】:

      .NET 中没有用于正确语言大写的预构建解决方案。你要什么样的大写?您是否遵循《芝加哥风格手册》的约定? AMA 还是 MLA?即使是简单的英文句子大写也有 1000 多个单词的特殊例外。我无法谈论 ruby​​ 的 humanize 做了什么,但我想它可能不遵循大写的语言规则,而是做一些更简单的事情。

      在内部,我们遇到了同样的问题,不得不编写相当多的代码来处理文章标题的正确(在我们的小世界中)大小写,甚至不考虑句子的大小写。它确实变得“模糊”:)

      这真的取决于你需要什么——你为什么要尝试将句子转换为正确的大写形式(以及在什么情况下)?

      【讨论】:

        【解决方案8】:

        如果您只想将第一个字符大写,只需将其粘贴到您自己的实用方法中即可:

        return string.IsNullOrEmpty(str) 
            ? str
            : str[0].ToUpperInvariant() + str.Substring(1).ToLowerInvariant();
        

        还有一个库方法可以将每个单词的第一个字符大写:

        http://msdn.microsoft.com/en-us/library/system.globalization.textinfo.totitlecase.aspx

        【讨论】:

        • 那只会给你标题案例:“Lorem Ipsum Et”,而不是句子案例:“Lorem ipsum et”,对吧?
        • 我认为恰恰相反。
        • 我在想这个,但 ToTitleCase 与 OP 想要的相反。
        • 我的错,我认为它会起作用,但它没有。 Titlecase 似乎可以解决问题
        • 呃……什么是 Titlecase?你是说 ToTitleCase 吗?它与您最初要求的相反。此外,这是我在原始答案中发布的第一件事。我放弃了。
        【解决方案9】:

        据我所知,如果不编写(或抄袭)代码,就没有办法做到这一点。 C# 网络(哈!)你的上、下和标题(你有什么)案例:

        http://support.microsoft.com/kb/312890/EN-US/

        【讨论】:

          猜你喜欢
          • 2010-12-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-10
          • 2018-10-24
          相关资源
          最近更新 更多