2013-11-11 1 views
-1

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

public static String toTitleCase(String s) 
{ 
    String result = ""; 
    String[] words = s.split(" "); 

    for (int i = 0; i < words.length; i++) 
    { 
     result += words[i].replace(words[i].charAt(0)+"", Character.toUpperCase(words[i].charAt(0))+"") + " "; 
    } 

    return result; 
} 

Проблема заключается в том, что метод преобразует каждую другую букву словом, которое является той же буквой, что и первая в верхнем регистре. Например, строка заголовка выходит как TITLE

Для входа this is a title это становится выходным This Is A TiTle

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

Что я могу сделать? Я хочу только первую букву в верхнем регистре.

ответ

3

Вместо того, чтобы использовать метод replace(), попробуйте replaceFirst().

result += words[i].replaceFirst(words[i].charAt(0)+"", Character.toUpperCase(words[i].charAt(0))+"") + " "; 

Выведет:

This Is A Title 
0

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

  • использование replaceFirst вместо
    1. взять первую букву,
    2. создать его прописную версию
    3. приписать к нему остальной части строки, которая может быть создана с небольшой помощью метода substring.
  • , так как вы используете replace(String, String), который использует регулярное выражение вы можете добавить ^ прежде, чем символ, который вы хотите заменить, как replace("^a","A"). ^ означает начало ввода, поэтому он заменяет только a, который помещается после начала ввода.

Возможно, я использовал бы второй подход.


Также в настоящее время в каждом цикле код создает новый StringBuilder с данными, хранящимися в result, append новое слово в ней, и переназначение result выхода из toString().
Это инфекционный подход. Вместо этого вы должны создать StringBuilder перед циклом, который будет представлять ваш результат, и append новых слов, созданных внутри цикла, и после окончания цикла вы можете получить его версию String с помощью метода toString().

0

Делая некоторые Regex-Magic может упростить задачу:

public static void main(String[] args) { 
    final String test = "this is a Test"; 

    final StringBuffer buffer = new StringBuffer(test); 
    final Pattern patter = Pattern.compile("\\b(\\p{javaLowerCase})"); 
    final Matcher matcher = patter.matcher(buffer); 
    while (matcher.find()) { 
    buffer.replace(matcher.start(), matcher.end(), matcher.group().toUpperCase()); 
    } 

    System.out.println(buffer); 
} 

Выражение \\b(\\p{javaLowerCase}) матчи «начало слова, за которым следует строчной буквы», в то время как matcher.group() равно, Что внутри() в той части, которая соответствует. Пример. Применяя к «тесту» совпадения на «t», поэтому начало равно 0, конец - 1, а группа - «t». Это может легко пропустить даже огромное количество текста и заменить все буквы, требующие замены.

Кроме того: всегда рекомендуется использовать StringBuffer (или подобное) для манипуляции строками, потому что каждая строка в Java уникальна. То есть, если вы делаете что-то вроде result += stringPart, вы фактически создаете новую String (равную результату + stringPart) каждый раз, когда это вызывается. Поэтому, если вы сделаете это с 10 частями, вы, в конце концов, получите по меньшей мере 10 различных строк в памяти, в то время как вам нужен только один, который является окончательным.

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

Обратите внимание, что необходимо только один раз скомпилировать patter, чтобы вы могли сохранить его как переменную класса.