Как преобразовать CamelCase в удобочитаемые имена на Java?
Я хотел бы написать метод, который преобразует CamelCase в удобочитаемое имя.
Здесь тестовый пример:
public void testSplitCamelCase() {
assertEquals("lowercase", splitCamelCase("lowercase"));
assertEquals("Class", splitCamelCase("Class"));
assertEquals("My Class", splitCamelCase("MyClass"));
assertEquals("HTML", splitCamelCase("HTML"));
assertEquals("PDF Loader", splitCamelCase("PDFLoader"));
assertEquals("A String", splitCamelCase("AString"));
assertEquals("Simple XML Parser", splitCamelCase("SimpleXMLParser"));
assertEquals("GL 11 Version", splitCamelCase("GL11Version"));
}
Ответы
Ответ 1
Это работает с вашими тестовыми тестами:
static String splitCamelCase(String s) {
return s.replaceAll(
String.format("%s|%s|%s",
"(?<=[A-Z])(?=[A-Z][a-z])",
"(?<=[^A-Z])(?=[A-Z])",
"(?<=[A-Za-z])(?=[^A-Za-z])"
),
" "
);
}
Здесь проверочный жгут:
String[] tests = {
"lowercase", // [lowercase]
"Class", // [Class]
"MyClass", // [My Class]
"HTML", // [HTML]
"PDFLoader", // [PDF Loader]
"AString", // [A String]
"SimpleXMLParser", // [Simple XML Parser]
"GL11Version", // [GL 11 Version]
"99Bottles", // [99 Bottles]
"May5", // [May 5]
"BFG9000", // [BFG 9000]
};
for (String test : tests) {
System.out.println("[" + splitCamelCase(test) + "]");
}
Он использует регулярное выражение с нулевой длиной с lookbehind и lookforward, чтобы найти место для вставки пробелов. В основном есть 3 шаблона, и я использую String.format
, чтобы соединить их, чтобы сделать его более читаемым.
Три шаблона:
UC позади меня, UC, за которым следует LC передо мной
XMLParser AString PDFLoader
/\ /\ /\
не-UC позади меня, UC передо мной
MyClass 99Bottles
/\ /\
Письмо позади меня, без буквы передо мной
GL11 May5 BFG9000
/\ /\ /\
Ссылки
Связанные вопросы
Использование совпадений с нулевой длиной для разделения:
Ответ 2
Вы можете сделать это, используя org.apache.commons.lang.StringUtils
StringUtils.join(
StringUtils.splitByCharacterTypeCamelCase("ExampleTest"),
' '
);
Ответ 3
Если вам не нравятся "сложные" регулярные выражения, и они совсем не беспокоятся об эффективности, я использовал этот пример для достижения такого же эффекта в три этапа.
String name =
camelName.replaceAll("([A-Z][a-z]+)", " $1") // Words beginning with UC
.replaceAll("([A-Z][A-Z]+)", " $1") // "Words" of only UC
.replaceAll("([^A-Za-z ]+)", " $1") // "Words" of non-letters
.trim();
Он передает все вышеперечисленные тестовые примеры, включая цифры с цифрами.
Как я уже сказал, это не так хорошо, как использование одного регулярного выражения в некоторых других примерах здесь, но кто-то может найти его полезным.
Ответ 4
Вы можете использовать org.modeshape.common.text.Inflector.
В частности:
String humanize(String lowerCaseAndUnderscoredWords,
String... removableTokens)
Заглавная буква первого слова и превращает символы подчеркивания в пробелы и полосы, завершающие "_id" и любые прилагаемые съемные маркеры.
Артефакт Maven: org.modeshape: modeshape-common: 2.3.0.Final
в репозитории JBoss: https://repository.jboss.org/nexus/content/repositories/releases
Здесь JAR файл: https://repository.jboss.org/nexus/content/repositories/releases/org/modeshape/modeshape-common/2.3.0.Final/modeshape-common-2.3.0.Final.jar
Ответ 5
Следующее Regex может использоваться для идентификации капиталов внутри слов:
"((?<=[a-z0-9])[A-Z]|(?<=[a-zA-Z])[0-9]]|(?<=[A-Z])[A-Z](?=[a-z]))"
Он соответствует каждой заглавной букве, то есть эфиру, после неглавной буквы или цифры или за ней следует строчная буква и каждая цифра после буквы.
Как вставить пробел перед ними за пределами моих навыков Java =)
Отредактировано, чтобы включить регистр цифр и дело PDF-загрузчика.
Ответ 6
Я думаю, вам придется перебирать строку и обнаруживать изменения от строчных к верхним, от верхнего до нижнего, от алфавитного до числового, от цифрового до буквенного. При каждом изменении, которое вы обнаруживаете, вставляйте пробел с одним исключением: при изменении от верхнего и нижнего регистра вы вставляете пробел один символ раньше.
Ответ 7
Это работает в .NET... оптимизируется по своему вкусу. Я добавил комментарии, чтобы вы могли понять, что делает каждая часть. (RegEx может быть трудно понять)
public static string SplitCamelCase(string str)
{
str = Regex.Replace(str, @"([A-Z])([A-Z][a-z])", "$1 $2"); // Capital followed by capital AND a lowercase.
str = Regex.Replace(str, @"([a-z])([A-Z])", "$1 $2"); // Lowercase followed by a capital.
str = Regex.Replace(str, @"(\D)(\d)", "$1 $2"); //Letter followed by a number.
str = Regex.Replace(str, @"(\d)(\D)", "$1 $2"); // Number followed by letter.
return str;
}
Ответ 8
Оптимальное и короткое решение:
StringUtils.capitalize(StringUtils.join(StringUtils.splitByCharacterTypeCamelCase("yourCamelCaseText"), StringUtils.SPACE)); // Your Camel Case Text
Ответ 9
Я не является ниндзя регулярного выражения, поэтому я буду перебирать строку, сохраняя индексы текущей позиции и предыдущей позиции. Если текущая позиция является заглавной буквой, я бы вложил пробел после предыдущей позиции и увеличил каждый индекс.
Ответ 10
Для записи здесь используется почти (*) совместимая версия Scala:
object Str { def unapplySeq(s: String): Option[Seq[Char]] = Some(s) }
def splitCamelCase(str: String) =
String.valueOf(
(str + "A" * 2) sliding (3) flatMap {
case Str(a, b, c) =>
(a.isUpper, b.isUpper, c.isUpper) match {
case (true, false, _) => " " + a
case (false, true, true) => a + " "
case _ => String.valueOf(a)
}
} toArray
).trim
После компиляции он может быть использован непосредственно из Java, если соответствующий scala -library.jar находится в пути к классам.
(*) он не работает для ввода "GL11Version"
, для которого он возвращает "G L11 Version"
.
Ответ 11
Я взял Regex из полигенных смазочных материалов и превратил его в метод расширения объектов:
/// <summary>
/// Turns a given object into a sentence by:
/// Converting the given object into a <see cref="string"/>.
/// Adding spaces before each capital letter except for the first letter of the string representation of the given object.
/// Makes the entire string lower case except for the first word and any acronyms.
/// </summary>
/// <param name="original">The object to turn into a proper sentence.</param>
/// <returns>A string representation of the original object that reads like a real sentence.</returns>
public static string ToProperSentence(this object original)
{
Regex addSpacesAtCapitalLettersRegEx = new Regex(@"(?<=[A-Z])(?=[A-Z][a-z]) | (?<=[^A-Z])(?=[A-Z]) | (?<=[A-Za-z])(?=[^A-Za-z])", RegexOptions.IgnorePatternWhitespace);
string[] words = addSpacesAtCapitalLettersRegEx.Split(original.ToString());
if (words.Length > 1)
{
List<string> wordsList = new List<string> { words[0] };
wordsList.AddRange(words.Skip(1).Select(word => word.Equals(word.ToUpper()) ? word : word.ToLower()));
words = wordsList.ToArray();
}
return string.Join(" ", words);
}
Это превращает все в читаемое предложение. Он передает ToString на переданный объект. Затем он использует Regex, заданный полигенными смазочными материалами, для разделения строки. Затем он ToLowers каждое слово, кроме первого слова и любых аббревиатур. Думал, что это может быть полезно для кого-то там.
Ответ 12
RegEx должен работать, что-то вроде ([A-Z]{1})
. Это приведет к захвату всех "Письмо-писем", после чего вы сможете заменить их на \1
или как всегда ссылаться на группы RegEx на Java.
Ответ 13
http://code.google.com/p/inflection-js/
Вы можете связать методы String.underscore(). humanize(), чтобы взять строку CamelCase и преобразовать ее в удобочитаемую строку.