例子:
>>> convert('CamelCase')
'camel_case'
例子:
>>> convert('CamelCase')
'camel_case'
当前回答
轻度改编自https://stackoverflow.com/users/267781/matth 谁使用发电机。
def uncamelize(s):
buff, l = '', []
for ltr in s:
if ltr.isupper():
if buff:
l.append(buff)
buff = ''
buff += ltr
l.append(buff)
return '_'.join(l).lower()
其他回答
使用正则表达式可能是最短的,但这个解决方案更具可读性:
def to_snake_case(s):
snake = "".join(["_"+c.lower() if c.isupper() else c for c in s])
return snake[1:] if snake.startswith("_") else snake
一个使用正则表达式的可怕例子(你可以很容易地清理:)):
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”这样的情况,应该也很容易看到有改进的空间,因为下划线是无条件插入的。
以防有人需要转换一个完整的源文件,这里有一个脚本可以做到这一点。
# Copy and paste your camel case code in the string below
camelCaseCode ="""
cv2.Matx33d ComputeZoomMatrix(const cv2.Point2d & zoomCenter, double zoomRatio)
{
auto mat = cv2.Matx33d::eye();
mat(0, 0) = zoomRatio;
mat(1, 1) = zoomRatio;
mat(0, 2) = zoomCenter.x * (1. - zoomRatio);
mat(1, 2) = zoomCenter.y * (1. - zoomRatio);
return mat;
}
"""
import re
def snake_case(name):
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
def lines(str):
return str.split("\n")
def unlines(lst):
return "\n".join(lst)
def words(str):
return str.split(" ")
def unwords(lst):
return " ".join(lst)
def map_partial(function):
return lambda values : [ function(v) for v in values]
import functools
def compose(*functions):
return functools.reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x)
snake_case_code = compose(
unlines ,
map_partial(unwords),
map_partial(map_partial(snake_case)),
map_partial(words),
lines
)
print(snake_case_code(camelCaseCode))
这个网站上提出了非常好的RegEx:
(?<!^)(?=[A-Z])
如果python有一个字符串分割方法,它应该工作…
在Java中:
String s = "loremIpsum";
words = s.split("(?<!^)(?=[A-Z])");
我也在寻找同样问题的解决方案,只不过我需要一条链子;如。
"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"))
当然,您可以预先编译正则表达式,或者像其他解决方案中讨论的那样,使用下划线而不是连字符连接正则表达式。