Первое слово из PascalCase в нижнем регистре
У меня есть строка, которая содержит текст в PascalCase, и мне нужно извлечь из него первое слово и преобразовать его в нижний регистр:
assert firstWord('PmdExtension') == 'pmd'
assert firstWord('PMDExtension') == 'p'
assert firstWord('Pmd') == 'pmd'
assert firstWord('CodeQualityExtension') == 'code'
static String firstWord(String word) {
return '???'
}
Давайте сосредоточимся только на допустимых идентификаторах PascalCase (без каких-либо других символов, цифр и всегда начиная с заглавной буквы).
Каково было бы простое и чистое решение для моей проблемы?
я пробовал
word.split(/[A-Z]/).first().join(' ')
но он удаляет все заглавные буквы, а мне нужно их сохранить.
4 ответа
assert firstWord('PmdExtension') == 'pmd'
assert firstWord('PMDExtension') == 'p'
assert firstWord('Pmd') == 'pmd'
assert firstWord('CodeQualityExtension') == 'code'
assert firstWord('') == ''
assert firstWord(null) == ''
static String firstWord(String word) {
word ? word.split(/(?=\p{Lu})/)[0].toLowerCase() : ''
// A verbose way would be as below (omitting the null check for brevity)
// word[0].toLowerCase() + word[1..-1].takeWhile { Character.isLowerCase(it) }
}
Groovy найти оператор (=~
), кажется, делает работу хорошо:
static String firstWord(String word) {
word ? (word =~ /[A-Z][a-z]*/)[0].toLowerCase() : ''
}
Что-то вроде:
static String firstWord(String word) {
return word[0].toLowerCase()+word.split(['A'..'Z'].join('|'))[1]
}
inject
Метод можно использовать для накопления символов, пока не встретится вторая заглавная буква:
def firstWord(String word) {
def numCapsObserved = 0
def initVal = ""
word.inject(initVal, { val, letter ->
def result = val
if (letter ==~ /[A-Z]/) { numCapsObserved++ }
if (numCapsObserved < 2) {
result += letter.toLowerCase()
}
return result
})
}
assert firstWord('PmdExtension') == 'pmd'
assert firstWord('PMDExtension') == 'p'
assert firstWord('Pmd') == 'pmd'
assert firstWord('CodeQualityExtension') == 'code'