如何使用C#将每个单词的第一个字符或整个字符串的第一个字符大写?

113

我可以编写自己的算法来完成这个任务,但我认为在C#中应该有与ruby's humanize相当的功能。

我搜索了一下,但只找到了将日期转换为人性化格式的方法。

示例:

  • 将"Lorem Lipsum Et"转换为"Lorem lipsum et"的方法
  • 将"Lorem lipsum et"转换为"Lorem Lipsum Et"的方法

2
我喜欢因为某种原因说Lorem Lipsum ^^ - marcgg
3
总有正则表达式可用!string strToCap = strSource.ToLower(); Regex rCapitalize = new Regex("(?<=[!\.?]\s+)[A-Za-z]"); strToCap = rCapitalize.Replace(strToCap, m => { return m.Value.ToUpper(); });...但随之而来会有两个问题。 :) - rijipooh
3
由于被接受的答案链接到了一个与原问题相反的代码,我已经编辑了问题,以便询问两个方向,希望这个问题对未来遇到它的用户不会完全混淆。 - Daniel Earwicker
虽然 OP 的示例字符串可能没有提到,但很多人失去了标题大小写和大写的区别。标题大小写不会将常用单词大写,因此即使在上面的示例中它可以工作,但这是错误的解决方案。The Dog is Fast 与 The Dog Is Fast。后者是大写。 - demongolem
9个回答

171

正如在@miguel的答案的评论中所讨论的那样,您可以使用自.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”。

但是,如果你只想大写第一个字符,可以使用在这里提供的方法... 或者你可以分割字符串并将列表中的第一个字符大写:

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 

怎么会有这么多人不知道这个?这是一个非常棒的内置方法,谢谢。 - Paul C
2
发现ToTitleCase函数的问题,1st会变成1St。 - Yogurt The Wise
1
发现了 ToTitleCase 的第二个问题 -   会变成 &Nbsp;。 - Brain2000
2
@Brain2000 如果你知道字符串中有HTML实体,那么在使用ToTitleCase之前应该让你的代码处理它们。参考链接:https://dev59.com/kHVD5IYBdhLWcg3wAGiD - Spoike
2
MSDN链接已失效。 - slayernoah

57

还有一种优雅的解决方案:

在您的项目的静态类中定义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 !"

5
在传递给 ToTitleCase 之前,你还应该使用 title.ToLower()。否则,大写字母不会被替换。 - RA.

39

使用正则表达式可以使代码看起来更加简洁:

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

1
扩展答案: 字符串 s = "tHe Quick bRown fOx juMps over tHe LAzy doG"; s = Regex.Replace(s.ToLower(), @"(^\w)|(\s\w)", m => m.Value.ToUpper()); - mcandal
9
这个单行非正则表达式也可以工作:s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(value.ToLower()); - Yogi
2
@Roberto - "hEm" -> 正则表达式 = "HEm"; "hEm" -> TitleCase = "Hem" - zzxyz
我认为这个更简单 Regex.Replace(s, @"\b([a-z])", m => m.Value.ToUpper()) - John Henckel

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,则这是正确的解决方案。 - Alexander

2

这只会给你标题大小写:“Lorem Ipsum Et”,而不是句子大小写:“Lorem ipsum et”,对吗? - vinny
我认为这相反了。 - Çağdaş Tekin
我在想,但是ToTitleCase与OP想要的相反。 - Pat Hermens
我的错,我以为它会起作用,但实际上并没有。使用Titlecase似乎是解决问题的办法。 - marcgg
额...什么是Titlecase?你是指ToTitleCase吗?它做的是与你最初要求的相反的事情。而且,这是我在原始答案中发布的第一件事。我放弃了。 - Daniel Earwicker

1

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

上述大多数实现都可以,但它们没有解决以下问题:如果您有需要保留大小写单词的混合大小写单词,或者想要使用真正的标题大小写,例如:

"在美国哪里学习博士课程"

"IRS表格UB40a"

使用CultureInfo.CurrentCulture.TextInfo.ToTitleCase(string)将保留大写单词,例如 "sports and MLB baseball" 变为 "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服务中具有首字母缩略词和大写/小写单词的查找表,以便可以从一个地方维护混合大小写单词列表,并应用于许多依赖此函数的不同应用程序。


0

在.NET中,没有预先构建的解决方案来正确地进行语言大写。你想要什么样的大写方式?你遵循芝加哥手册的规定吗?AMA或MLA?即使是普通英语句子的大写也有成千上万个特殊单词例外。我不知道Ruby的humanize做了什么,但我想它可能不遵循语言大写规则,而是做一些更简单的事情。

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

这真的取决于你需要什么 - 你为什么要将句子转换为适当的大写方式(以及在什么上下文中)?


0

我已经使用自定义扩展方法实现了相同的功能。对于第一个子字符串的第一个字母,可以使用方法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.

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接