【问题标题】:ToPascalCase() C# for all caps AbbreviationsToPascalCase() C# 用于所有大写字母缩写
【发布时间】:2014-04-28 15:39:51
【问题描述】:

我正在使用 ReSharper 并尝试遵守它的默认规则。

在我的部分代码中,我需要将字符串属性更改为 PascalCase。

我尝试了很多方法,但找不到一种适用于所有大写缩写的方法。

前:

MPSUser --> Still MPSUser (should be MpsUser)
ArticleID --> Still Article ID (Should be ArticleId)
closeMethod --> Works and changes to CloseMethod

谁能帮我创建一个可以将任何字符串转换为 PascalCase 的方法? 谢谢!

【问题讨论】:

  • 请注意,您可以使用 ReSharper 注册缩写,它将允许在 PascalCased 名称中使用它们。例如,对于 ArticleID,您将 ID 注册为缩写,它将不再抱怨。

标签: .net regex c#-4.0 pascalcasing


【解决方案1】:

我所知道的用于转换为PascalCase 的唯一内置方法是TextInfo.ToTitleCase,并且它不会按设计处理全大写单词。为了解决这个问题,我制作了一个可以检测所有单词部分的自定义正则表达式,然后将它们单独转换为 Title/Pascal Case:

string ToPascalCase(string s)
{
    // Find word parts using the following rules:
    // 1. all lowercase starting at the beginning is a word
    // 2. all caps is a word.
    // 3. first letter caps, followed by all lowercase is a word
    // 4. the entire string must decompose into words according to 1,2,3.
    // Note that 2&3 together ensure MPSUser is parsed as "MPS" + "User".

    var m = Regex.Match(s, "^(?<word>^[a-z]+|[A-Z]+|[A-Z][a-z]+)+$");
    var g = m.Groups["word"];

    // Take each word and convert individually to TitleCase
    // to generate the final output.  Note the use of ToLower
    // before ToTitleCase because all caps is treated as an abbreviation.
    var t = Thread.CurrentThread.CurrentCulture.TextInfo;
    var sb = new StringBuilder();
    foreach (var c in g.Captures.Cast<Capture>())
        sb.Append(t.ToTitleCase(c.Value.ToLower()));
    return sb.ToString();
}

这个函数应该处理常见的用例:

s           | ToPascalCase(s)
MPSUser     | MpsUser
ArticleID   | ArticleId
closeMethod | CloseMethod

【讨论】:

    【解决方案2】:

    我从 mellamokb 的解决方案中大量借鉴了一些更全面的东西。例如,我想留下数字。此外,我希望将任何非字母、非数字字符用作分隔符。这里是:

        public static string ToPascalCase(this string s) {
            var result = new StringBuilder();
            var nonWordChars = new Regex(@"[^a-zA-Z0-9]+");
            var tokens = nonWordChars.Split(s);
            foreach (var token in tokens) {
                result.Append(PascalCaseSingleWord(token));
            }
    
            return result.ToString();
        }
    
        static string PascalCaseSingleWord(string s) {
            var match = Regex.Match(s, @"^(?<word>\d+|^[a-z]+|[A-Z]+|[A-Z][a-z]+|\d[a-z]+)+$");
            var groups = match.Groups["word"];
    
            var textInfo = Thread.CurrentThread.CurrentCulture.TextInfo;
            var result = new StringBuilder();
            foreach (var capture in groups.Captures.Cast<Capture>()) {
                result.Append(textInfo.ToTitleCase(capture.Value.ToLower()));
            }
            return result.ToString();
        }
    

    这是一个显示一些测试用例的 x 单元测试:

        [Theory]
        [InlineData("imAString", "ImAString")]
        [InlineData("imAlsoString", "ImAlsoString")]
        [InlineData("ImAlsoString", "ImAlsoString")]
        [InlineData("im_a_string", "ImAString")]
        [InlineData("im a string", "ImAString")]
        [InlineData("ABCAcronym", "AbcAcronym")]
        [InlineData("im_a_ABCAcronym", "ImAAbcAcronym")]
        [InlineData("im a ABCAcronym", "ImAAbcAcronym")]
        [InlineData("8ball", "8Ball")]
        [InlineData("im a 8ball", "ImA8Ball")]
        [InlineData("IM_ALL_CAPS", "ImAllCaps")]
        [InlineData("IM ALSO ALL CAPS", "ImAlsoAllCaps")]
        [InlineData("i-have-dashes", "IHaveDashes")]
        [InlineData("a8word_another_word", "A8WordAnotherWord")]
        public void WhenGivenString_ShouldPascalCaseIt(string input, string expectedResult) {
            var result = input.ToPascalCase();
            Assert.Equal(expectedResult, result);
        }
    

    【讨论】:

    • 像魅力一样工作。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多