Лучший способ преобразовать падеж Паскаля в предложение

Как лучше всего преобразовать регистр Паскаля (верхний регистр верблюда) в предложение.

Например, начиная с

"AwaitingFeedback"

и преобразовав это в

"Awaiting feedback"

C# предпочтительнее, но я мог бы преобразовать его из Java или подобного.

Дело верблюда ожидает обратной связи, а не ожидает обратной связи (случай Паскаля). Кроме того, то, что вы хотите делать, не совсем возможно. Как насчет отключения GPS? Есть ли достаточно общее решение для таких случаев?

kgiannakakis 27.11.2008 13:08

@kgiannakakis соответственно изменил вопрос. Я всегда забываю, как идут имена, особенно с верхним и нижним регистром Camel.

Garry Shutler 27.11.2008 13:49
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
75
2
23 390
16

Ответы 16

Псевдокод:

NewString = "";
Loop through every char of the string (skip the first one)
   If char is upper-case ('A'-'Z')
     NewString = NewString + ' ' + lowercase(char)
   Else
     NewString = NewString + char

Лучшие способы, возможно, могут быть выполнены с использованием регулярных выражений или подпрограмм замены строк (замените 'X' на 'x')

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

    string spacedString = System.Text.RegularExpressions.Regex.Replace(yourString, "\B([A-Z])", " \k");
    spacedString = spacedString.ToLower();

Я не знаю C#, но не думаю, что в разделе замены разрешены экранирования типа \ s: как язык узнает, нужно ли вставлять пробел, табуляцию или что-то еще? :-)

PhiLho 27.11.2008 12:46

Вы правы, должно быть проще заменить на четкое "".

Antoine 27.11.2008 12:49

Единственное, что я бы сказал, это вызовет "ожидание обратной связи"

Garry Shutler 27.11.2008 12:59

Ну, вам обязательно нужно удалить первый пробел и поставить первый символ выше. Возможно, добавьте перед шаблоном "\ B", чтобы не совпадать с первым символом.

Antoine 27.11.2008 13:09

Ну вот...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CamelCaseToString
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(CamelCaseToString("ThisIsYourMasterCallingYou"));   
        }

        private static string CamelCaseToString(string str)
        {
            if (str == null || str.Length == 0)
                return null;

            StringBuilder retVal = new StringBuilder(32);

            retVal.Append(char.ToUpper(str[0]));
            for (int i = 1; i < str.Length; i++ )
            {
                if (char.IsLower(str[i]))
                {
                    retVal.Append(str[i]);
                }
                else
                {
                    retVal.Append(" ");
                    retVal.Append(char.ToLower(str[i]));
                }
            }

            return retVal.ToString();
        }
    }
}

Вы должны ToUpper () первым символом, иначе ваша процедура не будет работать с истинным camelCase, только с PascalCase

David Wengier 27.11.2008 13:07

Да, приятный улов, я знал, что что-то не так (но не мог понять это), когда он сказал, что "AwaitingFeedback" - это верблюжий случай!

Autodidact 27.11.2008 13:18

Это легко сделать в JavaScript (или PHP и т. д.), Где вы можете определить функцию в вызове замены:

var camel = "AwaitingFeedbackDearMaster";
var sentence = camel.replace(/([A-Z].)/g, function (c) { return ' ' + c.toLowerCase(); });
alert(sentence);

Хотя я не решил проблему с начальной шапкой ... :-)

Теперь для решения Java:

String ToSentence(String camel)
{
  if (camel == null) return ""; // Or null...
  String[] words = camel.split("(?=[A-Z])");
  if (words == null) return "";
  if (words.length == 1) return words[0];
  StringBuilder sentence = new StringBuilder(camel.length());
  if (words[0].length() > 0) // Just in case of camelCase instead of CamelCase
  {
    sentence.append(words[0] + " " + words[1].toLowerCase());
  }
  else
  {
    sentence.append(words[1]);
  }
  for (int i = 2; i < words.length; i++)
  {
    sentence.append(" " + words[i].toLowerCase());
  }
  return sentence.toString();
}

System.out.println(ToSentence("AwaitingAFeedbackDearMaster"));
System.out.println(ToSentence(null));
System.out.println(ToSentence(""));
System.out.println(ToSentence("A"));
System.out.println(ToSentence("Aaagh!"));
System.out.println(ToSentence("stackoverflow"));
System.out.println(ToSentence("disableGPS"));
System.out.println(ToSentence("Ahh89Boo"));
System.out.println(ToSentence("ABC"));

Обратите внимание на трюк, позволяющий разделить предложение без потери символа ...

Вот основной способ сделать это, что я придумал, используя Regex

public static string CamelCaseToSentence(this string value)
{
    var sb = new StringBuilder();
    var firstWord = true;

    foreach (var match in Regex.Matches(value, "([A-Z][a-z]+)|[0-9]+"))
    {
        if (firstWord)
        {
            sb.Append(match.ToString());
            firstWord = false;
        }
        else
        {
            sb.Append(" ");
            sb.Append(match.ToString().ToLower());
        }
    }

    return sb.ToString();
}

Он также разделит числа, которые я не указал, но которые будут полезны.

string camel = "MyCamelCaseString";
string s = Regex.Replace(camel, "([A-Z])", " $1").ToLower().Trim();
Console.WriteLine(s.Substring(0,1).ToUpper() + s.Substring(1));

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

"^\w"

к верхнему

\U (i think)

Преимущественно уже ответил здесь

Небольшое изменение в принятом ответе, чтобы преобразовать вторую и последующие буквы с заглавной буквы в нижний регистр, поэтому измените

if (char.IsUpper(text[i]))                
    newText.Append(' ');            
newText.Append(text[i]);

к

if (char.IsUpper(text[i]))                
{
    newText.Append(' ');            
    newText.Append(char.ToLower(text[i]));
}
else
   newText.Append(text[i]);
public static string ToSentenceCase(this string str)
{
    return Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1]));
}

В версиях Visual Studio после 2015 года можно делать

public static string ToSentenceCase(this string str)
{
    return Regex.Replace(str, "[a-z][A-Z]", m => $"{m.Value[0]} {char.ToLower(m.Value[1])}");
}

По материалам: Преобразование регистра Паскаля в предложения с использованием регулярного выражения

Решение xquery, которое работает как для UpperCamel, так и для lowerCamel case:

Чтобы вывести регистр предложения (заглавными являются только первые символы первого слова):

declare function content:sentenceCase($string)
{
let $firstCharacter := substring($string, 1, 1)
let $remainingCharacters := substring-after($string, $firstCharacter)
return
concat(upper-case($firstCharacter),lower-case(replace($remainingCharacters, '([A-Z])', ' $1')))
};

Чтобы вывести регистр заголовка (первый символ каждого слова должен быть заглавным):

declare function content:titleCase($string)
{
let $firstCharacter := substring($string, 1, 1)
let $remainingCharacters := substring-after($string, $firstCharacter)
return
concat(upper-case($firstCharacter),replace($remainingCharacters, '([A-Z])', ' $1'))
};

Это работает для меня:

Regex.Replace(strIn, "([A-Z]{1,2}|[0-9]+)", " $1").TrimStart()

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

Drew Noakes 08.03.2011 21:48

Это может не вернуть то, что вы намереваетесь использовать для таких случаев, как AwaitingTFeedback или Awaiting9Feedback. Для меня лучше Джеф ответ (который возвращает Awaiting T Feedback и Awaiting9 Feedback соответственно).

nawfal 07.12.2017 09:18

Это похоже на @SSTA, но более эффективно, чем вызов TrimStart.

Regex.Replace("ThisIsMyCapsDelimitedString", "(\\B[A-Z])", " $1")

Обнаружил это в источнике MvcContrib, но, похоже, здесь еще не упоминается.

return Regex.Replace(input, "([A-Z])", " $1", RegexOptions.Compiled).Trim();

Я обнаружил, что делаю нечто подобное, и я благодарен за отправную точку этого обсуждения. Это мое решение, помещенное как метод расширения к строковому классу в контексте консольного приложения.

using System;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string piratese = "avastTharMatey";
            string ivyese = "CheerioPipPip";

            Console.WriteLine("{0}\n{1}\n", piratese.CamelCaseToString(), ivyese.CamelCaseToString());
            Console.WriteLine("For Pete\'s sake, man, hit ENTER!");
            string strExit = Console.ReadLine();
        }

    }

    public static class StringExtension
    {
        public static string CamelCaseToString(this string str)
        {
            StringBuilder retVal = new StringBuilder(32);

            if (!string.IsNullOrEmpty(str))
            {
                string strTrimmed = str.Trim();

                if (!string.IsNullOrEmpty(strTrimmed))
                {
                    retVal.Append(char.ToUpper(strTrimmed[0]));

                    if (strTrimmed.Length > 1)
                    {
                        for (int i = 1; i < strTrimmed.Length; i++)
                        {
                            if (char.IsUpper(strTrimmed[i])) retVal.Append(" ");

                            retVal.Append(char.ToLower(strTrimmed[i]));
                        }
                    }
                }
            }
            return retVal.ToString();
        }
    }
}

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

Короткий ответ

"AwaitingFeedback".Humanize() => Awaiting feedback

Длинный и описательный ответ

Humanizer может выполнять гораздо больше работы, другие примеры:

"PascalCaseInputStringIsTurnedIntoSentence".Humanize() => "Pascal case input string is turned into sentence"
"Underscored_input_string_is_turned_into_sentence".Humanize() => "Underscored input string is turned into sentence"
"Can_return_title_Case".Humanize(LetterCasing.Title) => "Can Return Title Case"
"CanReturnLowerCase".Humanize(LetterCasing.LowerCase) => "can return lower case"

Полный код:

using Humanizer;
using static System.Console;

namespace HumanizerConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            WriteLine("AwaitingFeedback".Humanize());
            WriteLine("PascalCaseInputStringIsTurnedIntoSentence".Humanize());
            WriteLine("Underscored_input_string_is_turned_into_sentence".Humanize());
            WriteLine("Can_return_title_Case".Humanize(LetterCasing.Title));
            WriteLine("CanReturnLowerCase".Humanize(LetterCasing.LowerCase));
        }
    }
}

Выход

Awaiting feedback

Pascal case input string is turned into sentence

Underscored input string is turned into sentence Can Return Title Case

can return lower case

Если вы предпочитаете писать свой собственный код на C#, вы можете добиться этого, написав некоторые элементы кода на C#, на которые уже ответили другие.

Просто потому, что все использовали Regex (кроме этот парень), вот реализация с StringBuilder, которая в моих тестах была примерно В 5 раз быстрее. Также включает проверку чисел.

"SomeBunchOfCamelCase2".FromCamelCaseToSentence == "Some Bunch Of Camel Case 2"

public static string FromCamelCaseToSentence(this string input) {
    if (string.IsNullOrEmpty(input)) return input;

    var sb = new StringBuilder();
    // start with the first character -- consistent camelcase and pascal case
    sb.Append(char.ToUpper(input[0]));

    // march through the rest of it
    for(var i = 1; i < input.Length; i++) {
        // any time we hit an uppercase OR number, it's a new word
        if (char.IsUpper(input[i]) || char.IsDigit(input[i])) sb.Append(' ');
        // add regularly
        sb.Append(input[i]);
    }

    return sb.ToString();
}

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

    /// <summary>
    /// Add a space before any capitalized letter (but not for a run of capitals or numbers)
    /// </summary>
    internal static string FromCamelCaseToSentence(string input)
    {
        if (string.IsNullOrEmpty(input)) return String.Empty;

        var sb = new StringBuilder();
        bool upper = true;

        for (var i = 0; i < input.Length; i++)
        {
            bool isUpperOrDigit = char.IsUpper(input[i]) || char.IsDigit(input[i]);
            // any time we transition to upper or digits, it's a new word
            if (!upper && isUpperOrDigit)
            {
                sb.Append(' ');
            }
            sb.Append(input[i]);
            upper = isUpperOrDigit;
        }

        return sb.ToString();
    }

А вот несколько тестов:

    [TestCase(null, ExpectedResult = "")]
    [TestCase("", ExpectedResult = "")]
    [TestCase("ABC", ExpectedResult = "ABC")]
    [TestCase("abc", ExpectedResult = "abc")]
    [TestCase("camelCase", ExpectedResult = "camel Case")]
    [TestCase("PascalCase", ExpectedResult = "Pascal Case")]
    [TestCase("Pascal123", ExpectedResult = "Pascal 123")]
    [TestCase("CustomerID", ExpectedResult = "Customer ID")]
    [TestCase("CustomABC123", ExpectedResult = "Custom ABC123")]
    public string CanSplitCamelCase(string input)
    {
        return FromCamelCaseToSentence(input);
    }

Хороший ответ. В моем проекте я добавил bool nextIsLower = i > 0 && i + 1 < source.Length && char.IsLower(source[i + 1]); и изменил выражение if на if ((!upper || nextIsLower) && isUpperOrDigit). Это отделяет аббревиатуры от слов, поэтому CustomABCWith123 становится Пользовательский ABC с 123 вместо Пользовательский ABC с 123. Могут быть дела, которыми я не занимался, и, конечно, мы с А не работаем.

stritch000 22.05.2020 09:30

Другие вопросы по теме