例子:
>>> convert('CamelCase')
'camel_case'
例子:
>>> convert('CamelCase')
'camel_case'
当前回答
我也在寻找同样问题的解决方案,只不过我需要一条链子;如。
"CamelCamelCamelCase" -> "Camel-camel-camel-case"
从这两个词的解决方案开始,我想到了以下几点:
"-".join(x.group(1).lower() if x.group(2) is None else x.group(1) \
for x in re.finditer("((^.[^A-Z]+)|([A-Z][^A-Z]+))", "stringToSplit"))
最复杂的逻辑是避免小写第一个单词。如果你不介意改变第一个词,这里有一个更简单的版本:
"-".join(x.group(1).lower() for x in re.finditer("(^[^A-Z]+|[A-Z][^A-Z]+)", "stringToSplit"))
当然,您可以预先编译正则表达式,或者像其他解决方案中讨论的那样,使用下划线而不是连字符连接正则表达式。
其他回答
避免使用库和正则表达式:
def camel_to_snake(s):
return ''.join(['_'+c.lower() if c.isupper() else c for c in s]).lstrip('_')
>>> camel_to_snake('ThisIsMyString')
'this_is_my_string'
def convert(name):
return reduce(
lambda x, y: x + ('_' if y.isupper() else '') + y,
name
).lower()
如果我们需要覆盖一个已经没有驼峰输入的情况:
def convert(name):
return reduce(
lambda x, y: x + ('_' if y.isupper() and not x.endswith('_') else '') + y,
name
).lower()
一个使用正则表达式的可怕例子(你可以很容易地清理:)):
def f(s):
return s.group(1).lower() + "_" + s.group(2).lower()
p = re.compile("([A-Z]+[a-z]+)([A-Z]?)")
print p.sub(f, "CamelCase")
print p.sub(f, "getHTTPResponseCode")
但适用于getHTTPResponseCode !
或者,使用lambda:
p = re.compile("([A-Z]+[a-z]+)([A-Z]?)")
print p.sub(lambda x: x.group(1).lower() + "_" + x.group(2).lower(), "CamelCase")
print p.sub(lambda x: x.group(1).lower() + "_" + x.group(2).lower(), "getHTTPResponseCode")
编辑:对于像“Test”这样的情况,应该也很容易看到有改进的空间,因为下划线是无条件插入的。
在包索引中有一个inflection库可以为您处理这些事情。在这种情况下,您将寻找inflection.underscore():
>>> inflection.underscore('CamelCase')
'camel_case'
看一看优秀的Schematics库
https://github.com/schematics/schematics
它允许你创建类型化的数据结构,可以序列化/反序列化从python到Javascript风格,例如:
class MapPrice(Model):
price_before_vat = DecimalType(serialized_name='priceBeforeVat')
vat_rate = DecimalType(serialized_name='vatRate')
vat = DecimalType()
total_price = DecimalType(serialized_name='totalPrice')