Jak przekonwertować CamelCase na nazwy czytelne dla człowieka w Javie?

Chciałbym napisać metodę, która przekształca CamelCase w nazwę czytelną dla człowieka.

Oto przypadek testowy:

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"));
}
Author: Frederik, 2010-04-01

12 answers

To działa z Twoimi testami:

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])"
      ),
      " "
   );
}

Oto uprząż testowa:

    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) + "]");
    }

Używa regex o zerowej długości z lookbehind i lookforward, aby znaleźć miejsce wstawiania spacji. Zasadniczo są 3 wzory i używam String.format, aby je połączyć, aby było bardziej czytelne.

Trzy wzory to:

UC za mną, UC a następnie LC przede mną

  XMLParser   AString    PDFLoader
    /\        /\           /\

Nie-UC za mną, UC przede mną

 MyClass   99Bottles
  /\        /\

List za mną, Nie-litera w front of me

 GL11    May5    BFG9000
  /\       /\      /\

Referencje

Podobne pytania

Użycie zerowej długości dopasowania lookarounds do podziału:

 304
Author: polygenelubricants,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:21

Możesz to zrobić używając org.apache.commons.lang.StringUtils

StringUtils.join(
     StringUtils.splitByCharacterTypeCamelCase("ExampleTest"),
     ' '
);
 97
Author: Ralph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-07 14:59:39

Jeśli nie lubisz "skomplikowanych" wyrażeń regularnych i wcale nie przejmujesz się wydajnością, użyłem tego przykładu, aby osiągnąć ten sam efekt w trzech etapach.

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();

Przechodzi wszystkie powyższe przypadki testowe, łącznie z tymi z cyframi.

Jak mówię, nie jest to tak dobre, jak użycie jednego wyrażenia regularnego w innych przykładach tutaj - ale ktoś może uznać to za przydatne.

 9
Author: jlb83,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-12 15:13:14

Możesz użyć org.modeshape.pospolite.tekst.Inflector .

Konkretnie:

String humanize(String lowerCaseAndUnderscoredWords,
    String... removableTokens) 

Pierwszy wyraz jest pisany wielkimi literami, A podkreślniki zamieniają się w spacje i paski kończące " _id " oraz wszelkie dołączone wymienne tokeny.

Artefakt Mavena to: org.modeshape: modeshape-common:2.3.0.Finał

W repozytorium JBoss: https://repository.jboss.org/nexus/content/repositories/releases

Oto plik JAR: https://repository.jboss.org/nexus/content/repositories/releases/org/modeshape/modeshape-common/2.3.0.Final/modeshape-common-2.3.0.Final.jar{[3]

 6
Author: Hendy Irawan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-18 06:35:35

Schludne i krótsze rozwiązanie:

StringUtils.capitalize(StringUtils.join(StringUtils.splitByCharacterTypeCamelCase("yourCamelCaseText"), StringUtils.SPACE)); // Your Camel Case Text
 5
Author: Sahil Chhabra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-26 04:10:16

Następujące wyrażenia regularne mogą być używane do identyfikacji wielkich liter w słowach:

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

Pasuje do każdej wielkiej litery, czyli eteru po nie-Wielkiej literze lub cyfrze lub po której następuje mała litera i każda cyfra po literze.

Jak wstawić spację przed nimi jest poza moimi umiejętnościami Javy=)

edytowane w celu uwzględnienia przypadku cyfry i przypadku Ładowarki PDF.

 1
Author: Jens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-01 10:53:27

Myślę, że będziesz musiał iterować nad łańcuchem znaków i wykryć zmiany z małych liter na Wielkie, wielkie na małe, Alfabetyczne na numeryczne, Numeryczne na Alfabetyczne. Przy każdej zmianie wykrywasz wstawianie spacji z jednym wyjątkiem: przy zmianie z górnej-na małą literę wstawiasz spację jeden znak przed.

 1
Author: Felix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-01 11:06:05

To działa w. NET ... Optymalizuj według własnych upodobań. Dodałem komentarze, abyś mógł zrozumieć, co robi każdy kawałek. (RegEx może być trudny do zrozumienia)

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;
}
 1
Author: Xinbi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-12 23:10:47

Dla przypomnienia, oto prawie ( * ) zgodna Wersja Scali:

  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

Po skompilowaniu może być używany bezpośrednio z Javy, jeśli odpowiednia biblioteka scala.jar jest w klasie.

(*) nie powiedzie się dla wejścia "GL11Version", dla którego zwraca "G L11 Version".

 0
Author: gerferra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-03 06:13:16

Wziąłem Regex z polygenelubricants i przekształciłem go w metodę rozszerzenia na obiektach:

    /// <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);
    }

To zamienia wszystko w czytelne zdanie. Wykonuje ToString na przekazanym obiekcie. Następnie używa wyrażeń regularnych podanych przez polygenelubricants, aby podzielić łańcuch. Następnie mówi się o każdym słowie z wyjątkiem pierwszego słowa i wszelkich akronimów. Pomyślałem, że może się komuś przydać.

 0
Author: vbullinger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-16 15:58:12

Nie jestem regex ninja, więc chciałbym iterację nad ciągiem, zachowując indeksy bieżącej pozycji jest sprawdzane i poprzedniej pozycji. Jeśli bieżąca pozycja jest wielką literą, wstawiłbym spację po poprzedniej pozycji i przyrost każdego indeksu.

 -1
Author: Joel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-04 00:20:26

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

Możesz łańcuchować Łańcuch.underscore ().humanize () metody pobierania ciągu CamelCase i przekształcania go w czytelny dla człowieka ciąg znaków.

 -3
Author: BeesonBison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-03 14:43:38