Який найкращий спосіб перетворити з Паскаля (верхній регістр верблюда) на речення.
Наприклад, починаючи з
"AwaitingFeedback"
і перетворюючи це на
"Awaiting feedback"
C # кращий, але я міг би перетворити його з Java або подібного.
Який найкращий спосіб перетворити з Паскаля (верхній регістр верблюда) на речення.
Наприклад, починаючи з
"AwaitingFeedback"
і перетворюючи це на
"Awaiting feedback"
C # кращий, але я міг би перетворити його з Java або подібного.
Відповіді:
public static string ToSentenceCase(this string str)
{
return Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1]));
}
У версіях візуальної студії після 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])}");
}
Засновано на: Перетворення регістру Паскаль у речення за допомогою регулярного виразу
Я вважаю за краще використовувати для цього гуманізатор . Humanizer - це портативна бібліотека класів, яка відповідає усім вашим потребам .NET для маніпулювання та відображення рядків, переліків, дат, часу, часових інтервалів, чисел та величин.
Коротка відповідь
"AwaitingFeedback".Humanize() => Awaiting feedback
Довга та описова відповідь
Гуманізатор може зробити набагато більше роботи. Інші приклади:
"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));
}
}
}
Вихідні дані
Очікування зворотного зв’язку
Рядок введення регістру Паскаля перетворюється на речення
Підкреслений вхідний рядок перетворюється на речення Can Return Title Case
може повернути малу літеру
Якщо ви віддаєте перевагу писати свій власний код C #, ви можете досягти цього, написавши деякі матеріали з коду C #, як відповіли інші.
Це працює для мене:
Regex.Replace(strIn, "([A-Z]{1,2}|[0-9]+)", " $1").TrimStart()
AwaitingTFeedbackі Awaiting9Feedback. Відповідь Джефа для мене краща (що повертається Awaiting T Feedbackі Awaiting9 Feedbackвідповідно).
Ось ідіть ...
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();
}
}
}
Це так само, як @SSTA, але є більш ефективним, ніж виклик TrimStart.
Regex.Replace("ThisIsMyCapsDelimitedString", "(\\B[A-Z])", " $1")
Ось основний спосіб зробити це, який я придумав, використовуючи 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();
}
Він також розділить номери, які я не вказав, але був би корисний.
Тільки тому, що всі використовували регулярний вираз (крім цього хлопця ), ось реалізація, 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();
}
Я б використав регулярний вираз, вставляючи пробіл перед кожним символом верхнього регістру, а потім опускаючи весь рядок.
string spacedString = System.Text.RegularExpressions.Regex.Replace(yourString, "\B([A-Z])", " \k");
spacedString = spacedString.ToLower();
string camel = "MyCamelCaseString";
string s = Regex.Replace(camel, "([A-Z])", " $1").ToLower().Trim();
Console.WriteLine(s.Substring(0,1).ToUpper() + s.Substring(1));
Редагувати: не помітив ваших вимог до корпусу, змінений відповідно. Ви можете використовувати обчислювач матчів, щоб зробити кожух, але я думаю, що підрядок простіше. Ви також можете обернути його в 2-й замін регулярного виразу, де ви зміните перший символ
"^\w"
до верхнього
\U (i think)
Це легко зробити в JavaScript (або PHP тощо), де ви можете визначити функцію у виклику replace:
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"));
Зверніть увагу на хитрість розділити речення, не втрачаючи жодного символу ...
Псевдокод:
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")
Рішення xquery, яке працює як для UpperCamel, так і для lowerCamel:
Для виведення регістру речення (лише перший символ першого слова пишеться з великої літери):
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'))
};
Я виявив, що роблю щось подібне, і я вдячний, що мав вихідну точку з цієї дискусії. Це моє рішення, розміщене як метод розширення класу рядків у контексті консольної програми.
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();
}
}
}
Більшість попередніх відповідей розділяють абревіатури та цифри, додаючи пробіл перед кожним символом. Я хотів, щоб абревіатури та числа зберігалися разом, тому я маю простий автомат, який виділяє простір кожного разу, коли вхід переходить з одного стану в інший.
/// <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 стає Custom ABC With 123 замість Custom ABCWith 123 . Можуть бути випадки, якими я не займався, і, звичайно, А і я не працюю.
Тут переважно вже відповідали
Невелика зміна прийнятої відповіді, щоб перетворити другу та наступні великі літери на малі регістри, тому змініть
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]);