如何在 python 中拆分 CamelCase

新手上路,请多包涵

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

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

所以我搜索并找到了这个 完美的正则表达式

 (?<=[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 社区在这个问题上的立场如何,所以我说:我对任何一个都很好。由于 200_success 的解决方案更简单,我接受它作为正确答案。

原文由 AplusKminus 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 407
2 个回答

正如@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]

原文由 200_success 发布,翻译遵循 CC BY-SA 4.0 许可协议

使用 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']

原文由 Jossef Harush Kadouri 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题