Как преобразовать 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"));
}
12 ответов:
это работает с вашими тестовыми кейсами:
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 /\ /\ /\
ссылки
вопросы
использование нулевой длины соответствия lookarounds для разделения:
Вы можете сделать это с помощью
org.apache.commons.lang.StringUtils
StringUtils.join( StringUtils.splitByCharacterTypeCamelCase("ExampleTest"), ' ' );
Если вам не нравятся "сложные" регулярные выражения, и вы совсем не беспокоитесь об эффективности, то я использовал этот пример для достижения того же эффекта в три этапа.
String name = camelName.replaceAll("([A-Z][a-z]+)", " ") // Words beginning with UC .replaceAll("([A-Z][A-Z]+)", " ") // "Words" of only UC .replaceAll("([^A-Za-z ]+)", " ") // "Words" of non-letters .trim();
Он пройдет все тесты выше, в том числе с цифрами.
можно использовать орг.modeshape.общий.текст.Инфлектор.
в частности:
String humanize(String lowerCaseAndUnderscoredWords, String... removableTokens)
заглавные буквы первого слова и превращает подчеркивания в пробелы и полосы, заканчивающиеся " _id " и любые поставляемые съемные маркеры.
артефакт Maven:орг.modeshape: modeshape-common: 2.3.0.Финал
в репозитории JBoss: https://repository.jboss.org/nexus/content/repositories/releases
аккуратное и более короткое решение:
StringUtils.capitalize(StringUtils.join(StringUtils.splitByCharacterTypeCamelCase("yourCamelCaseText"), StringUtils.SPACE)); // Your Camel Case Text
для определения заглавных букв внутри слов можно использовать следующее регулярное выражение:
"((?<=[a-z0-9])[A-Z]|(?<=[a-zA-Z])[0-9]]|(?<=[A-Z])[A-Z](?=[a-z]))"
он соответствует каждой заглавной букве, то есть эфиру после не заглавной буквы или цифры или после строчной буквы и каждой цифры после буквы.
Как вставить пробел перед ними выходит за рамки моих навыков Java=)
отредактировано, чтобы включить случай цифры и случай загрузчика PDF.
Я думаю, что вам придется перебирать строку и обнаруживать изменения от нижнего регистра к верхнему, от верхнего регистра к нижнему, от алфавитного к числовому, от числового к алфавитному. При каждом изменении вы обнаруживаете вставку пробела с одним исключением: при изменении с верхнего на нижний регистр вы вставляете пробел на один символ раньше.
это работает в .NET ... оптимизировать по своему вкусу. Я добавил комментарии, чтобы вы могли понять, что делает каждая часть. (Регулярное выражение может быть трудно понять)
public static string SplitCamelCase(string str) { str = Regex.Replace(str, @"([A-Z])([A-Z][a-z])", " "); // Capital followed by capital AND a lowercase. str = Regex.Replace(str, @"([a-z])([A-Z])", " "); // Lowercase followed by a capital. str = Regex.Replace(str, @"(\D)(\d)", " "); //Letter followed by a number. str = Regex.Replace(str, @"(\d)(\D)", " "); // Number followed by letter. return str; }
для записи, вот почти (*) совместимая версия 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-библиотека.jar находится в classpath.
(*) это не за вход
"GL11Version"
для которого он возвращает"G L11 Version"
.
Я взял регулярное выражение из polygenelubricants и превратил его в метод расширения на объектах:
/// <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 на переданном объекте. Затем он использует регулярное выражение, заданное polygenelubricants, чтобы разделить строку. Затем он допускает каждое слово, за исключением первого слова и любых аббревиатур. Думал, что это может быть полезно для кого-то там.
Я не ниндзя регулярных выражений, поэтому я бы перебирал строку, сохраняя индексы текущей позиции проверяемой и предыдущей позиции. Если текущая позиция является заглавной буквой, Я бы вставил пробел после предыдущей позиции и увеличил каждый индекс.
http://code.google.com/p/inflection-js/
вы могли бы приковать строку.подчеркивать.)(очеловечить() методы, чтобы взять строку CamelCase и преобразовать ее в удобочитаемую строку.