如何在python中进行CamelCase拆分

2024-05-19 01:05:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我想达到的目标是这样的:

>>> camel_case_split("CamelCaseXYZ")
['Camel', 'Case', 'XYZ']
>>> camel_case_split("XYZCamelCase")
['XYZ', 'Camel', 'Case']

所以我搜索并找到了这个perfect regular expression

(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])

作为下一个合乎逻辑的步骤,我试着:

>>> re.split("(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])", "CamelCaseXYZ")
['CamelCaseXYZ']

为什么这不起作用,我如何在python中实现链接问题的结果?

编辑:解决方案摘要

我用几个测试用例测试了所有提供的解决方案:

string:                 ''
AplusKminus:            ['']
casimir_et_hippolyte:   []
two_hundred_success:    []
kalefranz:              string index out of range # with modification: either [] or ['']

string:                 ' '
AplusKminus:            [' ']
casimir_et_hippolyte:   []
two_hundred_success:    [' ']
kalefranz:              [' ']

string:                 'lower'
all algorithms:         ['lower']

string:                 'UPPER'
all algorithms:         ['UPPER']

string:                 'Initial'
all algorithms:         ['Initial']

string:                 'dromedaryCase'
AplusKminus:            ['dromedary', 'Case']
casimir_et_hippolyte:   ['dromedary', 'Case']
two_hundred_success:    ['dromedary', 'Case']
kalefranz:              ['Dromedary', 'Case'] # with modification: ['dromedary', 'Case']

string:                 'CamelCase'
all algorithms:         ['Camel', 'Case']

string:                 'ABCWordDEF'
AplusKminus:            ['ABC', 'Word', 'DEF']
casimir_et_hippolyte:   ['ABC', 'Word', 'DEF']
two_hundred_success:    ['ABC', 'Word', 'DEF']
kalefranz:              ['ABCWord', 'DEF']

总之,您可以说@kalefranz的解决方案与问题不匹配(见上一个案例),而@casimir et hippolyte的解决方案占用了一个空间,因此违反了拆分不应更改单个部分的想法。剩下两个备选方案之间的唯一区别是,我的解决方案返回一个列表,空字符串输入中包含空字符串,而@200_success的解决方案返回一个空列表。 我不知道python社区对这个问题的看法,所以我说:我对任何一个都很满意。由于200u success的解决方案更简单,所以我接受它作为正确答案。


Tags: stringplusall解决方案etsuccesscasetwo
3条回答

正如@AplusKminus所解释的,re.split()从不在空模式匹配上拆分。因此,与其拆分,不如尝试查找感兴趣的组件。

下面是一个使用re.finditer()模拟拆分的解决方案:

def camel_case_split(identifier):
    matches = finditer('.+?(?:(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|$)', identifier)
    return [m.group(0) for m in matches]

使用re.sub()split()

import re

name = 'CamelCaseTest123'
splitted = re.sub('([A-Z][a-z]+)', r' \1', re.sub('([A-Z]+)', r' \1', name)).split()

结果

'CamelCaseTest123' -> ['Camel', 'Case', 'Test123']
'CamelCaseXYZ' -> ['Camel', 'Case', 'XYZ']
'XYZCamelCase' -> ['XYZ', 'Camel', 'Case']
'XYZ' -> ['XYZ']
'IPAddress' -> ['IP', 'Address']

大多数情况下,当您不需要检查字符串的格式时,全局搜索比拆分更简单(对于相同的结果):

re.findall(r'[A-Z](?:[a-z]+|[A-Z]*(?=[A-Z]|$))', 'CamelCaseXYZ')

回报

['Camel', 'Case', 'XYZ']

要处理dromedary,也可以使用:

re.findall(r'[A-Z]?[a-z]+|[A-Z]+(?=[A-Z]|$)', 'camelCaseXYZ')

注意:(?=[A-Z]|$)可以使用双反(带反字符类的负展望)来缩短:(?![^A-Z])

相关问题 更多 >

    热门问题