3

我有一个包含 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

4 回答 4

3
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) }
}
于 2016-08-26T15:23:51.297 回答
2

Groovy 查找运算符 ( =~) 似乎很好地完成了这项工作:

static String firstWord(String word) {
    word ? (word =~ /[A-Z][a-z]*/)[0].toLowerCase() : ''
}
于 2016-08-26T20:30:07.997 回答
2

就像是:

static String firstWord(String word) {
    return word[0].toLowerCase()+word.split(['A'..'Z'].join('|'))[1]
}
于 2016-08-26T12:19:15.923 回答
1

The inject method can be used to accumulate characters until the second capital letter is encountered:

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'
于 2016-08-26T13:50:05.557 回答