Как я могу преобразовать текст в регистр Pascal?

У меня есть имя переменной, скажем "WARD_VS_VITAL_SIGNS", и я хочу преобразовать его в формат регистра Pascal: "WardVsVitalSigns"

WARD_VS_VITAL_SIGNS -> WardVsVitalSigns

Как я могу сделать это преобразование?

11 ответов

Решение

Во-первых, вы запрашиваете заглавный регистр, а не верблюжий регистр, потому что в верблюжьем регистре первая буква слова строчная, а ваш пример показывает, что вы хотите, чтобы первая буква была заглавной.

В любом случае, вот как вы можете достичь желаемого результата:

string textToChange = "WARD_VS_VITAL_SIGNS";
System.Text.StringBuilder resultBuilder = new System.Text.StringBuilder();

foreach(char c in textToChange)
{
    // Replace anything, but letters and digits, with space
    if(!Char.IsLetterOrDigit(c))
    {
        resultBuilder.Append(" ");
    }
    else 
    { 
        resultBuilder.Append(c); 
    }
}

string result = resultBuilder.ToString();

// Make result string all lowercase, because ToTitleCase does not change all uppercase correctly
result = result.ToLower();

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

result = myTI.ToTitleCase(result).Replace(" ", String.Empty);

Замечания: result сейчас WardVsVitalSigns,

Если вы действительно хотите использовать чехол для верблюда, то после всего вышеперечисленного просто используйте эту вспомогательную функцию:

public string LowercaseFirst(string s)
{
    if (string.IsNullOrEmpty(s))
    {
        return string.Empty;
    }

    char[] a = s.ToCharArray();
    a[0] = char.ToLower(a[0]);

    return new string(a);
}

Таким образом, вы можете назвать это так:

result = LowercaseFirst(result);

Вам не нужно регулярное выражение для этого.

var yourString = "WARD_VS_VITAL_SIGNS".ToLower().Replace("_", " ");
TextInfo info = CultureInfo.CurrentCulture.TextInfo;
yourString = info.ToTitleCase(yourString).Replace(" ", string.Empty);
Console.WriteLine(yourString);

Вы можете изменить код по своему усмотрению.

Вот мое быстрое решение LINQ & regex, чтобы сэкономить время:

using System;
using System.Linq;
using System.Text.RegularExpressions;

public string ToPascalCase(string original)
{
    Regex invalidCharsRgx = new Regex("[^_a-zA-Z0-9]");
    Regex whiteSpace = new Regex(@"(?<=\s)");
    Regex startsWithLowerCaseChar = new Regex("^[a-z]");
    Regex firstCharFollowedByUpperCasesOnly = new Regex("(?<=[A-Z])[A-Z0-9]+$");
    Regex lowerCaseNextToNumber = new Regex("(?<=[0-9])[a-z]");
    Regex upperCaseInside = new Regex("(?<=[A-Z])[A-Z]+?((?=[A-Z][a-z])|(?=[0-9]))");

    // replace white spaces with undescore, then replace all invalid chars with empty string
    var pascalCase = invalidCharsRgx.Replace(whiteSpace.Replace(original, "_"), string.Empty)
        // split by underscores
        .Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries)
        // set first letter to uppercase
        .Select(w => startsWithLowerCaseChar.Replace(w, m => m.Value.ToUpper()))
        // replace second and all following upper case letters to lower if there is no next lower (ABC -> Abc)
        .Select(w => firstCharFollowedByUpperCasesOnly.Replace(w, m => m.Value.ToLower()))
        // set upper case the first lower case following a number (Ab9cd -> Ab9Cd)
        .Select(w => lowerCaseNextToNumber.Replace(w, m => m.Value.ToUpper()))
        // lower second and next upper case letters except the last if it follows by any lower (ABcDEf -> AbcDef)
        .Select(w => upperCaseInside.Replace(w, m => m.Value.ToLower()));

    return string.Concat(pascalCase);
}

Пример вывода:

"WARD_VS_VITAL_SIGNS"          "WardVsVitalSigns"
"Who am I?"                    "WhoAmI"
"I ate before you got here"    "IAteBeforeYouGotHere"
"Hello|Who|Am|I?"              "HelloWhoAmI"
"Live long and prosper"        "LiveLongAndProsper"
"Lorem ipsum dolor..."         "LoremIpsumDolor"
"CoolSP"                       "CoolSp"
"AB9CD"                        "Ab9Cd"
"CCCTrigger"                   "CccTrigger"
"CIRC"                         "Circ"
"ID_SOME"                      "IdSome"
"ID_SomeOther"                 "IdSomeOther"
"ID_SOMEOther"                 "IdSomeOther"
"CCC_SOME_2Phases"             "CccSome2Phases"
"AlreadyGoodPascalCase"        "AlreadyGoodPascalCase"
"999 999 99 9 "                "999999999"
"1 2 3 "                       "123"
"1 AB cd EFDDD 8"              "1AbCdEfddd8"
"INVALID VALUE AND _2THINGS"   "InvalidValueAnd2Things"

Одиночная точка с запятой:

public static string PascalCase(this string word)
{
    return string.Join(" " , word.Split(' ')
                 .Select(w => w.Trim())
                 .Where(w => w.Length > 0)
                 .Select(w => w.Substring(0,1).ToUpper() + w.Substring(1).ToLower()));
}

Метод расширения для System.String с.NET Core совместимым кодом с помощью System а также System.Linq,

Не изменяет исходную строку.

.NET Fiddle для кода ниже

using System;
using System.Linq;

public static class StringExtensions
{
    /// <summary>
    /// Converts a string to PascalCase
    /// </summary>
    /// <param name="str">String to convert</param>

    public static string ToPascalCase(this string str){

        // Replace all non-letter and non-digits with an underscore and lowercase the rest.
        string sample = string.Join("", str?.Select(c => Char.IsLetterOrDigit(c) ? c.ToString().ToLower() : "_").ToArray());

        // Split the resulting string by underscore
        // Select first character, uppercase it and concatenate with the rest of the string
        var arr = sample?
            .Split(new []{'_'}, StringSplitOptions.RemoveEmptyEntries)
            .Select(s => $"{s.Substring(0, 1).ToUpper()}{s.Substring(1)}");

        // Join the resulting collection
        sample = string.Join("", arr);

        return sample;
    }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine("WARD_VS_VITAL_SIGNS".ToPascalCase()); // WardVsVitalSigns
        Console.WriteLine("Who am I?".ToPascalCase()); // WhoAmI
        Console.WriteLine("I ate before you got here".ToPascalCase()); // IAteBeforeYouGotHere
        Console.WriteLine("Hello|Who|Am|I?".ToPascalCase()); // HelloWhoAmI
        Console.WriteLine("Live long and prosper".ToPascalCase()); // LiveLongAndProsper
        Console.WriteLine("Lorem ipsum dolor sit amet, consectetur adipiscing elit.".ToPascalCase()); // LoremIpsumDolorSitAmetConsecteturAdipiscingElit
    }
}

Некоторые ответы верны, но я действительно не понимаю, почему они сначала устанавливают текст в LowerCase, потому что ToTitleCase будет обрабатывать это автоматически:

var text = "WARD_VS_VITAL_SIGNS".Replace("_", " ");

TextInfo textInfo = CultureInfo.CurrentCulture.TextInfo;
text = textInfo.ToTitleCase(text).Replace(" ", string.Empty);

Console.WriteLine(text);

Вы можете использовать это:

      public static string ConvertToPascal(string underScoreString)
    {
        string[] words = underScoreString.Split('_');

        StringBuilder returnStr = new StringBuilder();

        foreach (string wrd in words)
        {
            returnStr.Append(wrd.Substring(0, 1).ToUpper());
            returnStr.Append(wrd.Substring(1).ToLower());

        }
        return returnStr.ToString();
    }

Если вы хотите заменить любую отформатированную строку в случае паскаля, вы можете сделать

          public static string ToPascalCase(this string original)
    {
        string newString = string.Empty;
        bool makeNextCharacterUpper = false;
        for (int index = 0; index < original.Length; index++)
        {
            char c = original[index];
            if(index == 0)
                newString += $"{char.ToUpper(c)}";
            else if (makeNextCharacterUpper)
            {
                newString += $"{char.ToUpper(c)}";
                makeNextCharacterUpper = false;
            }
            else if (char.IsUpper(c))
                newString += $" {c}";
            else if (char.IsLower(c) || char.IsNumber(c))
                newString += c;
            else if (char.IsNumber(c))
                newString += $"{c}";
            else
            {
                makeNextCharacterUpper = true;   
                newString += ' ';
            }
        }

        return newString.TrimStart().Replace(" ", "");
    }

Протестировано со строками I|Can|Get|A|String ICan_GetAString i-can-get-a-string i_can_get_a_string I Can Get A String ICanGetAString

var xs = "WARD_VS_VITAL_SIGNS".Split('_');

var q =

    from x in xs

    let first_char = char.ToUpper(x[0]) 
    let rest_chars = new string(x.Skip(1).Select(c => char.ToLower(c)).ToArray())

    select first_char + rest_chars;

В этом ответе понимается, что есть категории Unicode, которые можно коснуться во время обработки текста, чтобы игнорировать соединительные символы, такие как - или _. На языке регулярных выражений это \p (для категории), то тип, который является {Pc}для знаков препинания и типа соединителя ; \p{Pc}.

Поэтому мы заменяем только слова и игнорируем знаки препинания при замене. Когда у нас есть слово, сдвиньте его вниз до нижнего регистра и до первого символа вверх:

      public static class StringExtensions
{
    public static string ToPascalCase(this string initial)
        => Regex.Replace(initial, 
                         // (Match any non punctuation) & then ignore any punctuation
                         @"([^\p{Pc}]+)[\p{Pc}]*", 
                         new MatchEvaluator(mtch =>
        {
            var word = mtch.Groups[1].Value.ToLower();

            return $"{Char.ToUpper(word[0])}{word.Substring(1)}";
        }));
}

Использование:

      "TOO_MUCH_BABY".ToPascalCase(); // TooMuchBaby
"HELLO|ITS|ME".ToPascalCase();  // HelloItsMe

См. Символ слова в классах символов в регулярных выражениях

Пунктуация ПК, разъем. В эту категорию входят десять символов, наиболее часто используемый из которых - символ LOWLINE (_), u+005F.

Я нашел эту суть полезной после добавления ToLower() к нему.

"WARD_VS_VITAL_SIGNS".ToLower().Split(new [] {"_"}, StringSplitOptions.RemoveEmptyEntries).Select(s => char.ToUpperInvariant(s[0]) + s.Substring(1, s.Length - 1)).Aggregate(string.Empty, (s1, s2) => s1 + s2)
Другие вопросы по тегам