Вопрос по java, string – Преобразование строки в титульный регистр

88

Существуют ли какие-либо встроенные методы для преобразования строки в формат Title Case как таковой?

Каждый, кто читает этот вопрос: остерегайтесь того, что многие из самых популярных проголосовавших здесь ответов НЕ РАБОТАЮТ ПРАВИЛЬНО для всех языков. Вам нужна библиотека с поддержкой i18n для правильного ввода заглавных букв, например, ICU4J (см. Ответ Daniel F). sffc

Ваш Ответ

16   ответов
0

содержащей регистр верблюдов, пробелы, цифры и другие символы. Но ни одно из доступных решений не сработало. В конце концов, я построил один для себя.

/*
 * Copyright (C) 2018 Sudipto Chandra
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * Convert a string to title case in java (with tests).
 *
 * @author Sudipto Chandra
 */
public abstract class TitleCase {

    /**
     * Returns the character type. <br>
     * <br>
     * Digit = 2 <br>
     * Lower case alphabet = 0 <br>
     * Uppercase case alphabet = 1 <br>
     * All else = -1.
     *
     * @param ch
     * @return
     */
    private static int getCharType(char ch) {
        if (Character.isLowerCase(ch)) {
            return 0;
        } else if (Character.isUpperCase(ch)) {
            return 1;
        } else if (Character.isDigit(ch)) {
            return 2;
        }
        return -1;
    }

    /**
     * Converts any given string in camel or snake case to title case.
     * <br>
     * It uses the method getCharType and ignore any character that falls in
     * negative character type category. It separates two alphabets of not-equal
     * cases with a space. It accepts numbers and append it to the currently
     * running group, and puts a space at the end.
     * <br>
     * If the result is empty after the operations, original string is returned.
     *
     * @param text the text to be converted.
     * @return a title cased string
     */
    public static String titleCase(String text) {
        if (text == null || text.length() == 0) {
            return text;
        }

        char[] str = text.toCharArray();
        StringBuilder sb = new StringBuilder();

        boolean capRepeated = false;
        for (int i = 0, prev = -1, next; i < str.length; ++i, prev = next) {
            next = getCharType(str[i]);
            // trace consecutive capital cases
            if (prev == 1 && next == 1) {
                capRepeated = true;
            } else if (next != 0) {
                capRepeated = false;
            }
            // next is ignorable
            if (next == -1) {
                // System.out.printf("case 0, %d %d %s\n", prev, next, sb.toString());
                continue; // does not append anything
            }
            // prev and next are of same type
            if (prev == next) {
                sb.append(str[i]);
                // System.out.printf("case 1, %d %d %s\n", prev, next, sb.toString());
                continue;
            }
            // next is not an alphabet
            if (next == 2) {
                sb.append(str[i]);
                // System.out.printf("case 2, %d %d %s\n", prev, next, sb.toString());
                continue;
            }
            // next is an alphabet, prev was not +
            // next is uppercase and prev was lowercase
            if (prev == -1 || prev == 2 || prev == 0) {
                if (sb.length() != 0) {
                    sb.append(' ');
                }
                sb.append(Character.toUpperCase(str[i]));
                // System.out.printf("case 3, %d %d %s\n", prev, next, sb.toString());
                continue;
            }
            // next is lowercase and prev was uppercase
            if (prev == 1) {
                if (capRepeated) {
                    sb.insert(sb.length() - 1, ' ');
                    capRepeated = false;
                }
                sb.append(str[i]);
                // System.out.printf("case 4, %d %d %s\n", prev, next, sb.toString());
            }
        }
        String output = sb.toString().trim();
        output = (output.length() == 0) ? text : output;
        //return output;

        // Capitalize all words (Optional)
        String[] result = output.split(" ");
        for (int i = 0; i < result.length; ++i) {
            result[i] = result[i].charAt(0) + result[i].substring(1).toLowerCase();
        }
        output = String.join(" ", result);
        return output;
    }

    /**
     * Test method for the titleCase() function.
     */
    public static void testTitleCase() {
        System.out.println("--------------- Title Case Tests --------------------");
        String[][] samples = {
            {null, null},
            {"", ""},
            {"a", "A"},
            {"aa", "Aa"},
            {"aaa", "Aaa"},
            {"aC", "A C"},
            {"AC", "Ac"},
            {"aCa", "A Ca"},
            {"ACa", "A Ca"},
            {"aCamel", "A Camel"},
            {"anCamel", "An Camel"},
            {"CamelCase", "Camel Case"},
            {"camelCase", "Camel Case"},
            {"snake_case", "Snake Case"},
            {"toCamelCaseString", "To Camel Case String"},
            {"toCAMELCase", "To Camel Case"},
            {"_under_the_scoreCamelWith_", "Under The Score Camel With"},
            {"ABDTest", "Abd Test"},
            {"title123Case", "Title123 Case"},
            {"expect11", "Expect11"},
            {"all0verMe3", "All0 Ver Me3"},
            {"___", "___"},
            {"__a__", "A"},
            {"_A_b_c____aa", "A B C Aa"},
            {"_get$It132done", "Get It132 Done"},
            {"_122_", "122"},
            {"_no112", "No112"},
            {"Case-13title", "Case13 Title"},
            {"-no-allow-", "No Allow"},
            {"_paren-_-allow--not!", "Paren Allow Not"},
            {"Other.Allow.--False?", "Other Allow False"},
            {"$39$ldl%LK3$lk_389$klnsl-32489  3 42034 ", "39 Ldl Lk3 Lk389 Klnsl32489342034"},
            {"tHis will BE MY EXAMple", "T His Will Be My Exa Mple"},
            {"stripEvery.damn-paren- -_now", "Strip Every Damn Paren Now"},
            {"getMe", "Get Me"},
            {"whatSthePoint", "What Sthe Point"},
            {"n0pe_aLoud", "N0 Pe A Loud"},
            {"canHave SpacesThere", "Can Have Spaces There"},
            {"  why_underScore exists  ", "Why Under Score Exists"},
            {"small-to-be-seen", "Small To Be Seen"},
            {"toCAMELCase", "To Camel Case"},
            {"_under_the_scoreCamelWith_", "Under The Score Camel With"},
            {"last one onTheList", "Last One On The List"}
        };
        int pass = 0;
        for (String[] inp : samples) {
            String out = titleCase(inp[0]);
            //String out = WordUtils.capitalizeFully(inp[0]);
            System.out.printf("TEST '%s'\nWANTS '%s'\nFOUND '%s'\n", inp[0], inp[1], out);
            boolean passed = (out == null ? inp[1] == null : out.equals(inp[1]));
            pass += passed ? 1 : 0;
            System.out.println(passed ? "-- PASS --" : "!! FAIL !!");
            System.out.println();
        }
        System.out.printf("\n%d Passed, %d Failed.\n", pass, samples.length - pass);
    }

    public static void main(String[] args) {
        // run tests
        testTitleCase();
    }
}

Вот некоторые входные данные:

aCamel
TitleCase
snake_case
fromCamelCASEString
ABCTest
expect11
_paren-_-allow--not!
  why_underScore   exists  
last one onTheList 

И мои выводы:

A Camel
Title Case
Snake Case
From Camel Case String
Abc Test
Expect11
Paren Allow Not
Why Under Score Exists
Last One On The List
10

WordUtils.capitalizeFully("this is a text to be capitalize")

Вы можете найти документацию по Java здесь: WordUtils.capitalizeFully Java документ

и если вы хотите удалить пробелы между мирами, вы можете использовать:

StringUtils.remove(WordUtils.capitalizeFully("this is a text to be capitalize")," ")

Вы можете найти документацию по Java для String StringUtils.remove Java документ

Я надеюсь, что это поможет.

5

андартом Unicode, вы должны использовать icu4j.

UCharacter.toTitleCase(Locale.US, "hello world", null, 0);

Обратите внимание, что это чувствительно к локали.

Api Документация

Реализация

Также доступно в Android API уровня 24:developer.android.com/reference/android/icu/lang/…
Также посмотрите более новую CaseMap API ICU4J:icu-project.org/apiref/icu4j/com/ibm/icu/text/…
56

два варианта:

using commons lang string utils.
 StringUtils.capitalize(null)  = null
 StringUtils.capitalize("")    = ""
 StringUtils.capitalize("cat") = "Cat"
 StringUtils.capitalize("cAt") = "CAt"
 StringUtils.capitalize("'cat'") = "'cat'"
write (yet another) static helper method toTitleCase() Sample implementation
public static String toTitleCase(String input) {
    StringBuilder titleCase = new StringBuilder();
    boolean nextTitleCase = true;

    for (char c : input.toCharArray()) {
        if (Character.isSpaceChar(c)) {
            nextTitleCase = true;
        } else if (nextTitleCase) {
            c = Character.toTitleCase(c);
            nextTitleCase = false;
        }

        titleCase.append(c);
    }

    return titleCase.toString();
}
Testcase
    System.out.println(toTitleCase("string"));
    System.out.println(toTitleCase("another string"));
    System.out.println(toTitleCase("YET ANOTHER STRING"));

выходы:

String
Another String
YET ANOTHER STRING
... Если бы он включал это, разве ему не потребовался бы полный поиск по словарю, чтобы понять, было ли текущее слово именем? Это кажется немного для любого метода.
Разве это не разрыв с апострофом? Как насчет O 'Брайана, например.
Этот код почти идеален, потому что некоторые имена могут иметь препозиции, такие как de, del, della, dei, da, например, в Maria del Carmen, Maria da Silva, Maria della Salute и т. Д.coderanch.com/t/35096/Programming/…
Это хорошая небольшая процедура, но она не работает для более общего случая, когда строки могут представлять имена. В этом случае капитализация также должна происходить после апострофов и дефисов. Например. О'Коннор и Дж. Уилкс-Бут. Конечно, другие языки могут иметь дополнительные правила падежа.
0

StringUtils:

org.springframework.util.StringUtils.capitalize(someText);

В любом случае, если вы уже используете Spring, это позволит избежать использования другой платформы.

18

WordUtils.capitalizeFully () от Apache Commons.

WordUtils.capitalizeFully(null)        = null
WordUtils.capitalizeFully("")          = ""
WordUtils.capitalizeFully("i am FINE") = "I Am Fine"
Отличное решение! Спасибо! Но это не работает в 100% случаев, так как оно также капитализируется, например. & Quot; & Quot; в этом заголовке: «Это заголовок». Увидетьenglish.stackexchange.com/questions/14/…, Вы знаете какую-нибудь библиотеку, которая занимается этим?
1

что он более старый, но не содержит простого ответа, мне нужен этот метод для моего кодирования, поэтому я добавил здесь, простой в использовании.

public static String toTitleCase(String input) {
    input = input.toLowerCase();
    char c =  input.charAt(0);
    String s = new String("" + c);
    String f = s.toUpperCase();
    return f + input.substring(1);
}
-2

- использовать пакет googles org.apache.commons.lang.WordUtils.

System.out.println(WordUtils.capitalizeFully("tHis will BE MY EXAMple"));

Приведет ли это

This Will Be My Example

Я не уверен, почему он назван «capitalizeFully», где на самом деле функция не дает полного результата, но в любом случае это инструмент, который нам нужен.

Это называетсяcapitalizeFully потому что оно использует заглавные буквы в каждом слове, включая те, которые должны быть строчными в названии.grammar.about.com/od/tz/g/Title-Case.htm
Apache Commons не принадлежит Google. Он поддерживается Фондом программного обеспечения Apache.commons.apache.org
2

что я написал для преобразования snake_case в lowerCamelCase, но его можно легко настроить в соответствии с требованиями

private String convertToLowerCamel(String startingText)
{
    String[] parts = startingText.split("_");
    return parts[0].toLowerCase() + Arrays.stream(parts)
                    .skip(1)
                    .map(part -> part.substring(0, 1).toUpperCase() + part.substring(1).toLowerCase())
                    .collect(Collectors.joining());
}
Ваш ответ работает как талисман, однако решение, по-видимому, не обрабатывает последовательность из одного слова, возможно, условия if должно быть достаточно.
0

и, к сожалению, у меня появилось много имен, начинающихся с Mc и Mac, в итоге я использовал версию кода Скотта, которую я изменил, чтобы обрабатывать эти префиксы, чтобы она появилась здесь на тот случай, если кто-то захочет ее использовать. ,

Есть все еще крайние случаи, которые это пропускает, но худшее, что может случиться, - то, что буква будет строчной, когда она должна быть написана заглавными буквами.

/**
 * Get a nicely formatted representation of the name. 
 * Don't send this the whole name at once, instead send it the components.<br>
 * For example: andrew macnamara would be returned as:<br>
 * Andrew Macnamara if processed as a single string<br>
 * Andrew MacNamara if processed as 2 strings.
 * @param name
 * @return correctly formatted name
 */
public static String getNameTitleCase (String name) {
    final String ACTIONABLE_DELIMITERS = " '-/";
    StringBuilder sb = new StringBuilder();
    if (name !=null && !name.isEmpty()){                
        boolean capitaliseNext = true;
        for (char c : name.toCharArray()) {
            c = (capitaliseNext)?Character.toUpperCase(c):Character.toLowerCase(c);
            sb.append(c);
            capitaliseNext = (ACTIONABLE_DELIMITERS.indexOf((int) c) >= 0);
        }                       
        name = sb.toString();    
        if (name.startsWith("Mc") && name.length() > 2 ) {
            char c = name.charAt(2);
            if (ACTIONABLE_DELIMITERS.indexOf((int) c) < 0) {
                sb = new StringBuilder();
                sb.append (name.substring(0,2));
                sb.append (name.substring(2,3).toUpperCase());
                sb.append (name.substring(3));
                name=sb.toString();
            }               
        } else if (name.startsWith("Mac") && name.length() > 3) {
            char c = name.charAt(3);
            if (ACTIONABLE_DELIMITERS.indexOf((int) c) < 0) {
                sb = new StringBuilder();
                sb.append (name.substring(0,3));
                sb.append (name.substring(3,4).toUpperCase());
                sb.append (name.substring(4));
                name=sb.toString();
            }
        }
    }
    return name;    
}
-3

public class TitleCase {

    String title(String sent)
    {   
        sent =sent.trim();
        sent = sent.toLowerCase();
        String[] str1=new String[sent.length()];
        for(int k=0;k<=str1.length-1;k++){
            str1[k]=sent.charAt(k)+"";
    }

        for(int i=0;i<=sent.length()-1;i++){
            if(i==0){
                String s= sent.charAt(i)+"";
                str1[i]=s.toUpperCase();
                }
            if(str1[i].equals(" ")){
                String s= sent.charAt(i+1)+"";
                str1[i+1]=s.toUpperCase();
                }

            System.out.print(str1[i]);
            }

        return "";
        }

    public static void main(String[] args) {
        TitleCase a = new TitleCase();
        System.out.println(a.title("   enter your Statement!"));
    }
}
35

Следующий метод основан на том, который опубликовал dfa. Он вносит следующее существенное изменение (которое подходит для решения, в котором я нуждался в то время): он переводит все символы во входной строке в нижний регистр, если непосредственно перед ним не стоит «действующий разделитель». в этом случае символ приводится в верхний регистр.

Основное ограничение моей рутины заключается в том, что она предполагает, что «название дела» определяется одинаково для всех локалей и представляется теми же соглашениями о случаях, которые я использовал, и поэтому он менее полезен, чем код dfa в этом отношении.

public static String toDisplayCase(String s) {

    final String ACTIONABLE_DELIMITERS = " '-/"; // these cause the character following
                                                 // to be capitalized

    StringBuilder sb = new StringBuilder();
    boolean capNext = true;

    for (char c : s.toCharArray()) {
        c = (capNext)
                ? Character.toUpperCase(c)
                : Character.toLowerCase(c);
        sb.append(c);
        capNext = (ACTIONABLE_DELIMITERS.indexOf((int) c) >= 0); // explicit cast not needed
    }
    return sb.toString();
}

TEST VALUES

a string

maRTin o'maLLEY

john wilkes-booth

YET ANOTHER STRING

OUTPUTS

A String

Martin O'Malley

John Wilkes-Booth

Yet Another String

@mihi: также не будет работать с другими специализированными правилами, например. фамилии, такие как Макнамара или Макдональд.
Не будет (не будет), это также приведет к "ее" стать "ее" S "?
не будет работать с лигатурами типа & # x1C9 ;, заглавными буквами которых являются & # x1C7; но titlecase это & # x1C8 ;. использованиеCharacter.toTitleCase вместо.
Это правда. Это хорошо работает с именными полями, но, как вы заметили, не с общей прозой. Он даже не будет хорошо работать на всех именах, в частности на вулканцах (T 'Pau вместо T' pau).
но эти случаи по своей сути не могут быть исправлены. Использование правильной функции преобразования регистра (предполагается, что заглавные буквы используются для прописных букв слова, а не в верхнем регистре в соответствии с правилами Unicode)can быть сделано (и это легко).
1

основанный на ответах @ dfa и @ scottb, который обрабатывает любые не буквы / цифры:

public final class TitleCase {

    public static String toTitleCase(String input) {

        StringBuilder titleCase = new StringBuilder();
        boolean nextTitleCase = true;

        for (char c : input.toLowerCase().toCharArray()) {
            if (!Character.isLetterOrDigit(c)) {
                nextTitleCase = true;
            } else if (nextTitleCase) {
                c = Character.toTitleCase(c);
                nextTitleCase = false;
            }
            titleCase.append(c);
        }

        return titleCase.toString();
    }

}

Учитывая вход:

MARY ÄNN O’CONNEŽ-ŠUSLIK

выход

Mary Änn O’Connež-Šuslik

0

String s= "ThiS iS SomE Text";
String[] arr = s.split(" ");
s = "";
for (String s1 : arr) {
    s += WordUtils.capitalize(s1.toLowerCase()) + " ";
}
s = s.substring(0, s.length() - 1);

Результат: «Это какой-то текст»

95

StringUtils.capitalize () или жеWordUtils.capitalize ()

например:WordUtils.capitalize("i am FINE") = "I Am FINE" отWordUtils доктор

+1 за предложение использования библиотеки. Здравый смысл царит на этот раз. Однако я предлагаю использовать WordUtils вместо StringUtils, у него более гибкий набор параметров.
WordUtils.capitalizeFully () был для меня лучше, так как он дает: WordUtils.capitalizeFully (& quot; я в порядке) = "я в порядке" & quot;
Просто небольшое обновление, WordUtils перешел в Commons Text и устарел внутри Commons Lang
Ссылка на WordUtils:commons.apache.org/lang/api-2.5/org/apache/commons/lang/…
0

org.apache.commons.lang.WordUtils

или же

CaseFormat

из API Google.

Было бы полезно добавить метод и пример.
CaseFormat имеет только форматы, обычно используемые в идентификаторах программ (UpperCamel, lower-hypen, UPPER_UNDERSCORE и т. Д.), И поддерживает только текст ASCII. Это не будет хорошо работать для преобразования в титульный регистр.

Похожие вопросы