Сегодня мне понадобилось перевести строку произвольного содержания в camelCase.
В интернете в основном встретились узкоспециализированные методы, которые либо переводят только имена констант (по соглашениям Java, SOME_JAVA_NAMING_CONVENTION_CONST), либо только фразы, разделенные пробелами.
Мне этого категорически не хватало, нужна была бОльшая универсальность.
Как и подобает любому уважающему себя велосипедисту, я начал писать свой алгоритм, и немного увлёкся. Очнувшись от кода, я обнаружил, что функция переводит любые мною скормленные строки в нормальный camelCase или CamelCase.
Единственное, что она не делает — не запрещает цифры в начале получившейся строки (для соглашений JNC), но мне это и не нужно было (при необходимости дописывается одной строкой кода — пополнением ко второму, вложенному, условию).
Что получилось можете увидеть под катом.
Функция принимает два аргумента — собственно строку, и флаг, указывающий писать результат с большой буквы (недо-camelCase).
Делает она всё это за один проход. Код присыпан комментариями для новичков (кому и пишется эта шпаргалка).
При жалении второй аргумент можно безболезненно откусить.
Так же практически без изменений алгоритм портируется на javascript и C#.
В интернете в основном встретились узкоспециализированные методы, которые либо переводят только имена констант (по соглашениям Java, SOME_JAVA_NAMING_CONVENTION_CONST), либо только фразы, разделенные пробелами.
Мне этого категорически не хватало, нужна была бОльшая универсальность.
Как и подобает любому уважающему себя велосипедисту, я начал писать свой алгоритм, и немного увлёкся. Очнувшись от кода, я обнаружил, что функция переводит любые мною скормленные строки в нормальный camelCase или CamelCase.
Единственное, что она не делает — не запрещает цифры в начале получившейся строки (для соглашений JNC), но мне это и не нужно было (при необходимости дописывается одной строкой кода — пополнением ко второму, вложенному, условию).
Что получилось можете увидеть под катом.
Функция принимает два аргумента — собственно строку, и флаг, указывающий писать результат с большой буквы (недо-camelCase).
Делает она всё это за один проход. Код присыпан комментариями для новичков (кому и пишется эта шпаргалка).
При жалении второй аргумент можно безболезненно откусить.
Так же практически без изменений алгоритм портируется на javascript и C#.
/**
* Возвращает отформатированную в виде camelCase (или CamelCase) строку.
*
* @param string Исходная строка
* @param firstWordToLowerCase Начинать ли искомую строку с маленького символа (lowercase).
*/
public static String toCamelCase(String string, boolean firstWordToLowerCase) {
char currentChar, previousChar = '\u0000'; // Текущий и предыдущий символ прохода
StringBuilder result = new StringBuilder(); // Результат функции в виде строкового билдера
boolean firstLetterArrived = !firstWordToLowerCase; // Флаг, отвечающий за написание первого символа результата в lowercase
boolean nextLetterInUpperCase = true; // Флаг, приказывающий следующий добавляемый символ писать в UPPERCASE
// Проходимся по всем символам полученной строки
for (int i = 0; i < string.length(); i++) {
currentChar = string.charAt(i);
/* Если текущий символ не цифробуква -
приказываем следующий символ писать Большим (начать новое слово) и идем на следующую итерацию.
Если предыдущий символ это маленькая буква или цифра, а текущий это большая буква -
приказываем текущий символ писать Большим (начать новое слово).
*/
if (!Character.isLetterOrDigit(currentChar) || (
((Character.isLetter(previousChar) && Character.isLowerCase(previousChar)) || Character.isDigit(previousChar)) &&
Character.isLetter(currentChar) && Character.isUpperCase(currentChar))
) {
nextLetterInUpperCase = true;
if (!Character.isLetterOrDigit(currentChar)) {
previousChar = currentChar;
continue;
}
}
// Если приказано писать Большую букву, и первая буква уже написана.
if (nextLetterInUpperCase && firstLetterArrived) {
result.append(Character.toUpperCase(currentChar));
}
else {
result.append(Character.toLowerCase(currentChar));
}
// Устанавливаем флаги.
firstLetterArrived = true;
nextLetterInUpperCase = false;
previousChar = currentChar;
}
// Возвращаем полученный результат.
return result.toString();
}
Ну и примеры результатов функции
Source string: 'normalCamelCaseName'
Result string: 'normalCamelCaseName'
Result string: 'NormalCamelCaseName' (firstWordToLowerCase = false)
===========================
Source string: 'NotCamelCaseName'
Result string: 'notCamelCaseName'
Result string: 'NotCamelCaseName' (firstWordToLowerCase = false)
===========================
Source string: 'CONSTANT_TO_CAMEL_CASE'
Result string: 'constantToCamelCase'
Result string: 'ConstantToCamelCase' (firstWordToLowerCase = false)
===========================
Source string: 'Text To Camel Case'
Result string: 'textToCamelCase'
Result string: 'TextToCamelCase' (firstWordToLowerCase = false)
===========================
Source string: 'Text to camel case'
Result string: 'textToCamelCase'
Result string: 'TextToCamelCase' (firstWordToLowerCase = false)
===========================
Source string: 'ОтЖиМаЕмСя На ШиФфТе, ДрУзЯфФкИ!:)'
Result string: 'отЖиМаЕмСяНаШиФфТеДрУзЯфФкИ'
Result string: 'ОтЖиМаЕмСяНаШиФфТеДрУзЯфФкИ' (firstWordToLowerCase = false)
===========================
Source string: '-(*&*&%&%$^&^*()Знаков*&^%*(&$препинания… и.нечитаемых-----------знаков^ (Может*90Быть&(*?*?: СКОЛЬКО*?%?:%угодно!'
Result string: 'знаковПрепинанияИНечитаемыхЗнаковМожет90БытьСколькоУгодно'
Result string: 'ЗнаковПрепинанияИНечитаемыхЗнаковМожет90БытьСколькоУгодно' (firstWordToLowerCase = false)
===========================
Source string: 'И, напоследок, русская строка со знаками препинания (локализация!).'
Result string: 'иНапоследокРусскаяСтрокаСоЗнакамиПрепинанияЛокализация'
Result string: 'ИНапоследокРусскаяСтрокаСоЗнакамиПрепинанияЛокализация' (firstWordToLowerCase = false)