首页 文章

如何在Java中将CamelCase转换为人类可读的名称?

提问于
浏览
141

我想编写一个将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 回答

  • 306

    这适用于您的测试用例:

    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
      /\       /\      /\
    

    参考文献

    相关问题

    使用零长度匹配的外观来分割:

  • 6

    你可以用 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();
    

    它通过了上面的所有测试用例,包括带有数字的测试用例 .

    正如我所说,这不如在其他一些例子中使用一个正则表达式那么好 - 但有人可能会发现它很有用 .

  • 8

    整洁而简短的解决方案:

    StringUtils.capitalize(StringUtils.join(StringUtils.splitByCharacterTypeCamelCase("yourCamelCaseText"), StringUtils.SPACE)); // Your Camel Case Text
    
  • 98

    你可以使用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

  • 1

    以下正则表达式可用于识别单词内的大写:

    "((?<=[a-z0-9])[A-Z]|(?<=[a-zA-Z])[0-9]]|(?<=[A-Z])[A-Z](?=[a-z]))"
    

    它匹配每个大写字母,即非大写字母或数字之后的以太符号,或后跟小写字母和字母后的每个数字 .

    如何在它们之前插入空格超出了我的Java技能=)

    编辑包括数字案例和PDF Loader案例 .

  • 1

    我认为你将不得不迭代字符串并检测从小写到大写,从大写到小写,从字母到数字,从数字到字母的变化 . 在您检测到的每个更改中,插入一个空格,但有一个例外:在从大写到小写的更改中,您将空格插入前一个字符 .

  • -1

    这适用于.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;
    }
    
  • 0

    为了记录,这里是几乎(*)兼容的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
    

    编译后,如果相应的scala-library.jar位于类路径中,则可以直接从Java使用 .

    (*)输入 "GL11Version" 失败,返回 "G L11 Version" .

  • 9

    我从polygenelubricants中取出了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 . 然后它使用polygenelubricants给出的正则表达式来分割字符串 . 然后它除了第一个单词和任何首字母缩略词之外,还要除了每个单词 . 认为它可能对那里的人有用 .

  • 0

    我不是一个正则表达式的忍者,所以我会迭代字符串,保持当前位置的索引被检查和之前的位置 . 如果当前位置是大写字母,我会在前一个位置后插入一个空格并递增每个索引 .

  • 1

    http://code.google.com/p/inflection-js/

    您可以链接 String.underscore().humanize() 方法以获取CamelCase字符串并将其转换为人类可读的字符串 .

相关问题