Splitting CamelCase

前端 未结 15 2428
盖世英雄少女心
盖世英雄少女心 2020-12-07 10:56

This is all asp.net c#.

I have an enum

public enum ControlSelectionType 
{
    NotApplicable = 1,
    SingleSelectRadioButtons = 2,
    SingleSelectD         


        
相关标签:
15条回答
  • 2020-12-07 11:29

    Here's an extension method that handles numbers and multiple uppercase characters sanely, and also allows for upper-casing specific acronyms in the final string:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Globalization;
    using System.Text.RegularExpressions;
    using System.Web.Configuration;
    
    namespace System
    {
        /// <summary>
        /// Extension methods for the string data type
        /// </summary>
        public static class ConventionBasedFormattingExtensions
        {
            /// <summary>
            /// Turn CamelCaseText into Camel Case Text.
            /// </summary>
            /// <param name="input"></param>
            /// <returns></returns>
            /// <remarks>Use AppSettings["SplitCamelCase_AllCapsWords"] to specify a comma-delimited list of words that should be ALL CAPS after split</remarks>
            /// <example>
            /// wordWordIDWord1WordWORDWord32Word2
            /// Word Word ID Word 1 Word WORD Word 32 Word 2
            /// 
            /// wordWordIDWord1WordWORDWord32WordID2ID
            /// Word Word ID Word 1 Word WORD Word 32 Word ID 2 ID
            /// 
            /// WordWordIDWord1WordWORDWord32Word2Aa
            /// Word Word ID Word 1 Word WORD Word 32 Word 2 Aa
            /// 
            /// wordWordIDWord1WordWORDWord32Word2A
            /// Word Word ID Word 1 Word WORD Word 32 Word 2 A
            /// </example>
            public static string SplitCamelCase(this string input)
            {
                if (input == null) return null;
                if (string.IsNullOrWhiteSpace(input)) return "";
    
                var separated = input;
    
                separated = SplitCamelCaseRegex.Replace(separated, @" $1").Trim();
    
                //Set ALL CAPS words
                if (_SplitCamelCase_AllCapsWords.Any())
                    foreach (var word in _SplitCamelCase_AllCapsWords)
                        separated = SplitCamelCase_AllCapsWords_Regexes[word].Replace(separated, word.ToUpper());
    
                //Capitalize first letter
                var firstChar = separated.First(); //NullOrWhiteSpace handled earlier
                if (char.IsLower(firstChar))
                    separated = char.ToUpper(firstChar) + separated.Substring(1);
    
                return separated;
            }
    
            private static readonly Regex SplitCamelCaseRegex = new Regex(@"
                (
                    (?<=[a-z])[A-Z0-9] (?# lower-to-other boundaries )
                    |
                    (?<=[0-9])[a-zA-Z] (?# number-to-other boundaries )
                    |
                    (?<=[A-Z])[0-9] (?# cap-to-number boundaries; handles a specific issue with the next condition )
                    |
                    (?<=[A-Z])[A-Z](?=[a-z]) (?# handles longer strings of caps like ID or CMS by splitting off the last capital )
                )"
                , RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace
            );
    
            private static readonly string[] _SplitCamelCase_AllCapsWords =
                (WebConfigurationManager.AppSettings["SplitCamelCase_AllCapsWords"] ?? "")
                    .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(a => a.ToLowerInvariant().Trim())
                    .ToArray()
                    ;
    
            private static Dictionary<string, Regex> _SplitCamelCase_AllCapsWords_Regexes;
            private static Dictionary<string, Regex> SplitCamelCase_AllCapsWords_Regexes
            {
                get
                {
                    if (_SplitCamelCase_AllCapsWords_Regexes == null)
                    {
                        _SplitCamelCase_AllCapsWords_Regexes = new Dictionary<string,Regex>();
                        foreach(var word in _SplitCamelCase_AllCapsWords)
                            _SplitCamelCase_AllCapsWords_Regexes.Add(word, new Regex(@"\b" + word + @"\b", RegexOptions.Compiled | RegexOptions.IgnoreCase));
                    }
    
                    return _SplitCamelCase_AllCapsWords_Regexes;
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-07 11:31

    The solution from Eoin Campbell works good except if you have a Web Service.

    You would need to do the Following as the Description Attribute is not serializable.

    [DataContract]
    public enum ControlSelectionType
    {
        [EnumMember(Value = "Not Applicable")]
        NotApplicable = 1,
        [EnumMember(Value = "Single Select Radio Buttons")]
        SingleSelectRadioButtons = 2,
        [EnumMember(Value = "Completely Different Display Text")]
        SingleSelectDropDownList = 3,
    }
    
    
    public static string GetDescriptionFromEnumValue(Enum value)
    {
        EnumMemberAttribute attribute = value.GetType()
            .GetField(value.ToString())
            .GetCustomAttributes(typeof(EnumMemberAttribute), false)
            .SingleOrDefault() as EnumMemberAttribute;
        return attribute == null ? value.ToString() : attribute.Value;
    }
    
    0 讨论(0)
  • 2020-12-07 11:31

    And if you don't fancy using regex - try this:

    public static string SeperateByCamelCase(this string text, char splitChar = ' ') {
    
            var output = new StringBuilder();
    
            for (int i = 0; i < text.Length; i++)
            {
                var c = text[i];
    
                //if not the first and the char is upper
                if (i > 0 && char.IsUpper(c)) {
    
                    var wasLastLower = char.IsLower(text[i - 1]);
    
                    if (i + 1 < text.Length) //is there a next
                    {
                        var isNextUpper = char.IsUpper(text[i + 1]);
    
                        if (!isNextUpper) //if next is not upper (start of a word).
                        {
                            output.Append(splitChar);
                        }
                        else if (wasLastLower) //last was lower but i'm upper and my next is an upper (start of an achromin). 'abcdHTTP' 'abcd HTTP'
                        {
                            output.Append(splitChar);
                        }
                    }
                    else
                    {
                        //last letter - if its upper and the last letter was lower 'abcd' to 'abcd A'
                        if (wasLastLower)
                        {
                            output.Append(splitChar);
                        }
                    }
                }
    
                output.Append(c);
            }
    
    
            return output.ToString();
    
        }
    

    Passes these tests, it doesn't like numbers but i didn't need it to.

        [TestMethod()]
        public void ToCamelCaseTest()
        {
    
            var testData = new string[] { "AAACamel", "AAA", "SplitThisByCamel", "AnA", "doesnothing", "a", "A", "aasdasdAAA" };
            var expectedData = new string[] { "AAA Camel", "AAA", "Split This By Camel", "An A", "doesnothing", "a", "A", "aasdasd AAA" };
    
            for (int i = 0; i < testData.Length; i++)
            {
                var actual = testData[i].SeperateByCamelCase();
                var expected = expectedData[i];
                Assert.AreEqual(actual, expected);
            }
    
        }
    
    0 讨论(0)
  • 2020-12-07 11:32

    I also have an enum which I had to separate. In my case this method solved the problem-

    string SeparateCamelCase(string str)
    {
        for (int i = 1; i < str.Length; i++)
        {
            if (char.IsUpper(str[i]))
            {
                str = str.Insert(i, " ");
                i++;
            }
        }
        return str;
    }
    
    0 讨论(0)
  • 2020-12-07 11:33

    I used:

        public static string SplitCamelCase(string input)
        {
            return System.Text.RegularExpressions.Regex.Replace(input, "([A-Z])", " $1", System.Text.RegularExpressions.RegexOptions.Compiled).Trim();
        }
    

    Taken from http://weblogs.asp.net/jgalloway/archive/2005/09/27/426087.aspx

    vb.net:

    Public Shared Function SplitCamelCase(ByVal input As String) As String
        Return System.Text.RegularExpressions.Regex.Replace(input, "([A-Z])", " $1", System.Text.RegularExpressions.RegexOptions.Compiled).Trim()
    End Function
    
    0 讨论(0)
  • 2020-12-07 11:34

    #JustSayNoToRegex

    Takes a C# identifier, with uderscores and numbers, and converts it to space-separated string.

    public static class StringExtensions
    {
        public static string SplitOnCase(this string identifier)
        {
            if (identifier == null || identifier.Length == 0) return string.Empty;
            var sb = new StringBuilder();
    
            if (identifier.Length == 1) sb.Append(char.ToUpperInvariant(identifier[0]));
    
            else if (identifier.Length == 2) sb.Append(char.ToUpperInvariant(identifier[0])).Append(identifier[1]);
    
            else {
                if (identifier[0] != '_') sb.Append(char.ToUpperInvariant(identifier[0]));
                for (int i = 1; i < identifier.Length; i++) {
                    var current = identifier[i];
                    var previous = identifier[i - 1];
    
                    if (current == '_' && previous == '_') continue;
    
                    else if (current == '_') {
                        sb.Append(' ');
                    }
    
                    else if (char.IsLetter(current) && previous == '_') {
                        sb.Append(char.ToUpperInvariant(current));
                    }
    
                    else if (char.IsDigit(current) && char.IsLetter(previous)) {
                        sb.Append(' ').Append(current);
                    }
    
                    else if (char.IsLetter(current) && char.IsDigit(previous)) {
                        sb.Append(' ').Append(char.ToUpperInvariant(current));
                    }
    
                    else if (char.IsUpper(current) && char.IsLower(previous) 
                        && (i < identifier.Length - 1 && char.IsUpper(identifier[i + 1]) || i == identifier.Length - 1)) {
                            sb.Append(' ').Append(current);
                    }
    
                    else if (char.IsUpper(current) && i < identifier.Length - 1 && char.IsLower(identifier[i + 1])) {
                        sb.Append(' ').Append(current);
                    }
    
                    else {
                        sb.Append(current);
                    }
                }
            }
            return sb.ToString();
        }
    
    }
    

    Tests:

    [TestFixture]
    static class HelpersTests
    {
        [Test]
        public static void Basic()
        {
            Assert.AreEqual("Foo", "foo".SplitOnCase());
            Assert.AreEqual("Foo", "_foo".SplitOnCase());
            Assert.AreEqual("Foo", "__foo".SplitOnCase());
            Assert.AreEqual("Foo", "___foo".SplitOnCase());
            Assert.AreEqual("Foo 2", "foo2".SplitOnCase());
            Assert.AreEqual("Foo 23", "foo23".SplitOnCase());
            Assert.AreEqual("Foo 23 A", "foo23A".SplitOnCase());
            Assert.AreEqual("Foo 23 Ab", "foo23Ab".SplitOnCase());
            Assert.AreEqual("Foo 23 Ab", "foo23_ab".SplitOnCase());
            Assert.AreEqual("Foo 23 Ab", "foo23___ab".SplitOnCase());
            Assert.AreEqual("Foo 23", "foo__23".SplitOnCase());
            Assert.AreEqual("Foo Bar", "Foo_bar".SplitOnCase());
            Assert.AreEqual("Foo Bar", "Foo____bar".SplitOnCase());
            Assert.AreEqual("AAA", "AAA".SplitOnCase());
            Assert.AreEqual("Foo A Aa", "fooAAa".SplitOnCase());
            Assert.AreEqual("Foo AAA", "fooAAA".SplitOnCase());
            Assert.AreEqual("Foo Bar", "FooBar".SplitOnCase());
            Assert.AreEqual("Mn M", "MnM".SplitOnCase());
            Assert.AreEqual("AS", "aS".SplitOnCase());
            Assert.AreEqual("As", "as".SplitOnCase());
            Assert.AreEqual("A", "a".SplitOnCase());
            Assert.AreEqual("_", "_".SplitOnCase());
    
        }
    }
    
    0 讨论(0)
提交回复
热议问题