Misal:
>>> convert('CamelCase')
'camel_case'
NotCamelCase
amathisIs
Misal:
>>> convert('CamelCase')
'camel_case'
NotCamelCase
amathisIs
Yanıtlar:
import re
name = 'CamelCaseName'
name = re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()
print(name) # camel_case_name
Bunu birçok kez yaparsanız ve yukarıdakiler yavaşsa, normal ifadeyi önceden derleyin:
pattern = re.compile(r'(?<!^)(?=[A-Z])')
name = pattern.sub('_', name).lower()
Daha gelişmiş vakaları özel olarak ele almak için (bu artık geri döndürülemez):
def camel_to_snake(name):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()
print(camel_to_snake('camel2_camel2_case')) # camel2_camel2_case
print(camel_to_snake('getHTTPResponseCode')) # get_http_response_code
print(camel_to_snake('HTTPResponseCodeXYZ')) # http_response_code_xyz
name = 'snake_case_name'
name = ''.join(word.title() for word in name.split('_'))
print(name) # SnakeCaseName
not_camel_case
için notCamelCase
ve / veya NotCamelCase
?
s2.replace('__', '_')
Paket dizininde bunları sizin için halledebilecek bir çekim kütüphanesi var. Bu durumda, şunları arıyorsunuz inflection.underscore()
:
>>> inflection.underscore('CamelCase')
'camel_case'
Bunların neden bu kadar karmaşık olduğunu bilmiyorum.
çoğu durumda, basit ifade ([A-Z]+)
hile yapacak
>>> re.sub('([A-Z]+)', r'_\1','CamelCase').lower()
'_camel_case'
>>> re.sub('([A-Z]+)', r'_\1','camelCase').lower()
'camel_case'
>>> re.sub('([A-Z]+)', r'_\1','camel2Case2').lower()
'camel2_case2'
>>> re.sub('([A-Z]+)', r'_\1','camelCamelCase').lower()
'camel_camel_case'
>>> re.sub('([A-Z]+)', r'_\1','getHTTPResponseCode').lower()
'get_httpresponse_code'
İlk karakteri görmezden gelmek için arkasına bak (?!^)
>>> re.sub('(?!^)([A-Z]+)', r'_\1','CamelCase').lower()
'camel_case'
>>> re.sub('(?!^)([A-Z]+)', r'_\1','CamelCamelCase').lower()
'camel_camel_case'
>>> re.sub('(?!^)([A-Z]+)', r'_\1','Camel2Camel2Case').lower()
'camel2_camel2_case'
>>> re.sub('(?!^)([A-Z]+)', r'_\1','getHTTPResponseCode').lower()
'get_httpresponse_code'
ALLCaps'i all_caps'a ayırmak ve dizenizdeki sayıları beklemek istiyorsanız, yine de iki ayrı çalışma yapmanız gerekmez Sadece |
bu ifade ((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))
kitaptaki hemen hemen her senaryoyu işleyebilir
>>> a = re.compile('((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))')
>>> a.sub(r'_\1', 'getHTTPResponseCode').lower()
'get_http_response_code'
>>> a.sub(r'_\1', 'get2HTTPResponseCode').lower()
'get2_http_response_code'
>>> a.sub(r'_\1', 'get2HTTPResponse123Code').lower()
'get2_http_response123_code'
>>> a.sub(r'_\1', 'HTTPResponseCode').lower()
'http_response_code'
>>> a.sub(r'_\1', 'HTTPResponseCodeXYZ').lower()
'http_response_code_xyz'
Her şey ne istediğinize bağlıdır, bu yüzden aşırı karmaşık olmamalı, ihtiyaçlarınıza en uygun çözümü kullanın.
Njoy!
(?!^)
Arkasına bakma denilen ifadeden şaşkındım . Bir şeyi kaçırmadıkça, burada gerçekten istediğimiz şey, olarak ifade edilmesi gereken olumsuz bir bakış (?<!^)
. Olumsuz bakış (?!^)
"Camel2WARNING_Case_CASE"
olur "camel2_warning_case__case"
. Bunu (?<!_)
çözmek için negatif bir re.sub('((?<=[a-z0-9])[A-Z]|(?!^)(?<!_)[A-Z](?=[a-z]))', r'_\1', "Camel2WARNING_Case_CASE").lower()
'camel2_warning_case_case'
(?!^)
yanlış bir şekilde "arkasına bak" olarak adlandırıldı ve bunun yerine negatif bir ileri görüş iddiası olarak adlandırılmalıydı . Gibi bu güzel açıklama gösterileri, negatif lookaheads genellikle gelip sonra ifadesi için sen arama. Yani aklınıza gelebilecek (?!^)
"bulmak olarak ''
nerede <start of string>
takip etmez". Gerçekten de, olumsuz da geriye bakan çalışır: aklınıza gelebilecek (?<!^)
"buldukça ''
nerede <start of string>
değil Precede yok".
stringcase benim bunun için benim kütüphane olduğunu; Örneğin:
>>> from stringcase import pascalcase, snakecase
>>> snakecase('FooBarBaz')
'foo_bar_baz'
>>> pascalcase('foo_bar_baz')
'FooBarBaz'
Şahsen python'da düzenli ifadeler kullanan bir şeyin nasıl zarif olarak tanımlanabileceğinden emin değilim. Çoğu cevap sadece "kod golf" tipi RE hileler yapıyor. Zarif kodlamanın kolayca anlaşılması gerekiyor.
def to_snake_case(not_snake_case):
final = ''
for i in xrange(len(not_snake_case)):
item = not_snake_case[i]
if i < len(not_snake_case) - 1:
next_char_will_be_underscored = (
not_snake_case[i+1] == "_" or
not_snake_case[i+1] == " " or
not_snake_case[i+1].isupper()
)
if (item == " " or item == "_") and next_char_will_be_underscored:
continue
elif (item == " " or item == "_"):
final += "_"
elif item.isupper():
final += "_"+item.lower()
else:
final += item
if final[0] == "_":
final = final[1:]
return final
>>> to_snake_case("RegularExpressionsAreFunky")
'regular_expressions_are_funky'
>>> to_snake_case("RegularExpressionsAre Funky")
'regular_expressions_are_funky'
>>> to_snake_case("RegularExpressionsAre_Funky")
'regular_expressions_are_funky'
+=
iplerde neredeyse her zaman kötü bir fikirdir. Bir listeye ekleyin ''.join()
ve sonunda listeye ekleyin . Veya bu durumda, sadece bir alt çizgi ile katılın ...
re
Mümkünse kaçınmayı tercih ederim :
def to_camelcase(s):
return ''.join(['_' + c.lower() if c.isupper() else c for c in s]).lstrip('_')
>>> to_camelcase("ThisStringIsCamelCase")
'this_string_is_camel_case'
re
kütüphaneyi kullanmaktan ve sadece yerleşik satır yöntemlerini kullanarak bir satırda bir şeyler yapmaktan kaçınan en kompakt olanıdır! Bu cevaba benzer , ancak if ... else
potansiyel olarak eklenen "_" karakterini ilk karakter olarak sıyırarak dilimleme ve ilave kullanmaktan kaçınır . Bunu en çok seviyorum.
6.81 µs ± 22.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
ama bu cevap 2.51 µs ± 25.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
için 2,5 kat daha hızlı! Bunu sev!
Bu çözümün önceki yanıtlardan daha basit olduğunu düşünüyorum:
import re
def convert (camel_input):
words = re.findall(r'[A-Z]?[a-z]+|[A-Z]{2,}(?=[A-Z][a-z]|\d|\W|$)|\d+', camel_input)
return '_'.join(map(str.lower, words))
# Let's test it
test_strings = [
'CamelCase',
'camelCamelCase',
'Camel2Camel2Case',
'getHTTPResponseCode',
'get200HTTPResponseCode',
'getHTTP200ResponseCode',
'HTTPResponseCode',
'ResponseHTTP',
'ResponseHTTP2',
'Fun?!awesome',
'Fun?!Awesome',
'10CoolDudes',
'20coolDudes'
]
for test_string in test_strings:
print(convert(test_string))
Hangi çıktılar:
camel_case
camel_camel_case
camel_2_camel_2_case
get_http_response_code
get_200_http_response_code
get_http_200_response_code
http_response_code
response_http
response_http_2
fun_awesome
fun_awesome
10_cool_dudes
20_cool_dudes
Normal ifade üç kalıpla eşleşir:
[A-Z]?[a-z]+
: İsteğe bağlı olarak büyük harfle başlayan ardışık küçük harfler.[A-Z]{2,}(?=[A-Z][a-z]|\d|\W|$)
: İki veya daha fazla ardışık büyük harf. Sonrasında büyük harf olan küçük harfin ardından gelen büyük harfleri hariç tutmak için bir ileriye bakar.\d+
: Ardışık sayılar.Kullanarak re.findall
, küçük harfe dönüştürülebilen ve alt çizgi ile birleştirilebilen tek tek "kelimelerin" bir listesini alırız.
Neden her iki .sub () çağrılarını kullanarak fikrim yok? :) Ben regex guru değilim, ama bazı ihtiyaçları için uygun olan bu fonksiyon basitleştirilmiş, ben sadece POST isteği vars_with_underscore için camelCasedVars dönüştürmek için bir çözüm gerekli:
def myFunc(...):
return re.sub('(.)([A-Z]{1})', r'\1_\2', "iTriedToWriteNicely").lower()
GetHTTPResponse gibi isimlerle çalışmaz, çünkü kötü adlandırma kuralı olduğunu duydum (getHttpResponse gibi olmalı, açıkçası, bu formu ezberlemek çok daha kolay).
'HTTPConnectionFactory'
, kodunuz üreten 'h_tt_pconnection_factory'
kabul edilen cevabını kod üretir,'http_connection_factory'
İşte benim çözümüm:
def un_camel(text):
""" Converts a CamelCase name into an under_score name.
>>> un_camel('CamelCase')
'camel_case'
>>> un_camel('getHTTPResponseCode')
'get_http_response_code'
"""
result = []
pos = 0
while pos < len(text):
if text[pos].isupper():
if pos-1 > 0 and text[pos-1].islower() or pos-1 > 0 and \
pos+1 < len(text) and text[pos+1].islower():
result.append("_%s" % text[pos].lower())
else:
result.append(text[pos].lower())
else:
result.append(text[pos])
pos += 1
return "".join(result)
Yorumlarda tartışılan köşe davalarını destekler. Örneğin, dönüştürmek gerekir getHTTPResponseCode
için get_http_response_code
olması gerektiği gibi.
Eğlenmek için:
>>> def un_camel(input):
... output = [input[0].lower()]
... for c in input[1:]:
... if c in ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
... output.append('_')
... output.append(c.lower())
... else:
... output.append(c)
... return str.join('', output)
...
>>> un_camel("camel_case")
'camel_case'
>>> un_camel("CamelCase")
'camel_case'
Veya eğlenmek için daha fazlası:
>>> un_camel = lambda i: i[0].lower() + str.join('', ("_" + c.lower() if c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" else c for c in i[1:]))
>>> un_camel("camel_case")
'camel_case'
>>> un_camel("CamelCase")
'camel_case'
str.join
çağlar boyunca kullanımdan kaldırıldı . ''.join(..)
Bunun yerine kullanın .
Regexes kullanmak en kısa olabilir, ancak bu çözüm çok daha okunabilir:
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
Çok karmaşık yöntemler ... Sadece tüm "Başlıklı" grubunu bulun ve alt kasalı varyantını alt çizgi ile birleştirin.
>>> import re
>>> def camel_to_snake(string):
... groups = re.findall('([A-z0-9][a-z]*)', string)
... return '_'.join([i.lower() for i in groups])
...
>>> camel_to_snake('ABCPingPongByTheWay2KWhereIsOurBorderlands3???')
'a_b_c_ping_pong_by_the_way_2_k_where_is_our_borderlands_3'
Grubun ilk karakteri veya ayrı bir grup gibi sayılar yapmak istemiyorsanız ([A-z][a-z0-9]*)
maske kullanabilirsiniz .
Standart kütüphanede değil, ancak ihtiyacınız olan işlevselliği içerdiği görülen bu komut dosyasını buldum .
Bu zarif bir yöntem değil, basit bir durum makinesinin (bitfield durum makinesi) çok 'düşük seviyeli' bir uygulamasıdır, muhtemelen bunu çözmek için en anti pitonik moddur, ancak yeniden modül de bu basitliği çözmek için çok karmaşık bir durum makinesi uygular görev, bu yüzden bu iyi bir çözüm olduğunu düşünüyorum.
def splitSymbol(s):
si, ci, state = 0, 0, 0 # start_index, current_index
'''
state bits:
0: no yields
1: lower yields
2: lower yields - 1
4: upper yields
8: digit yields
16: other yields
32 : upper sequence mark
'''
for c in s:
if c.islower():
if state & 1:
yield s[si:ci]
si = ci
elif state & 2:
yield s[si:ci - 1]
si = ci - 1
state = 4 | 8 | 16
ci += 1
elif c.isupper():
if state & 4:
yield s[si:ci]
si = ci
if state & 32:
state = 2 | 8 | 16 | 32
else:
state = 8 | 16 | 32
ci += 1
elif c.isdigit():
if state & 8:
yield s[si:ci]
si = ci
state = 1 | 4 | 16
ci += 1
else:
if state & 16:
yield s[si:ci]
state = 0
ci += 1 # eat ci
si = ci
print(' : ', c, bin(state))
if state:
yield s[si:ci]
def camelcaseToUnderscore(s):
return '_'.join(splitSymbol(s))
splitsymbol tüm vaka tiplerini ayrıştırabilir: UpperSEQUENCEInterleaved, under_score, BIG_SYMBOLS ve cammelCasedMethods
Umarım faydalı olur
Jeneratör kullanan https://stackoverflow.com/users/267781/matth'dan hafifçe uyarlandı .
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()
Mükemmel Schematics lib'ine bir göz atın
https://github.com/schematics/schematics
Python'dan Javascript lezzetine seri hale getirebilen / serisini kaldırabilecek yazılı veri yapıları oluşturmanıza olanak tanır, örneğin:
class MapPrice(Model):
price_before_vat = DecimalType(serialized_name='priceBeforeVat')
vat_rate = DecimalType(serialized_name='vatRate')
vat = DecimalType()
total_price = DecimalType(serialized_name='totalPrice')
Bu basit yöntem işi yapmalıdır:
import re
def convert(name):
return re.sub(r'([A-Z]*)([A-Z][a-z]+)', lambda x: (x.group(1) + '_' if x.group(1) else '') + x.group(2) + '_', name).rstrip('_').lower()
( buradan alınır, çevrimiçi çalışma örneğine bakın )
Vay be bunu sadece django parçacıklarından çaldım. ref http://djangosnippets.org/snippets/585/
Oldukça zarif
camelcase_to_underscore = lambda str: re.sub(r'(?<=[a-z])[A-Z]|[A-Z](?=[^A-Z])', r'_\g<0>', str).lower().strip('_')
Misal:
camelcase_to_underscore('ThisUser')
İadeler:
'this_user'
Düzenli ifadeler kullanan korkunç bir örnek (bunu kolayca temizleyebilirsiniz :)):
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")
Gerçi getHTTPResponseCode için çalışıyor!
Alternatif olarak, lambda kullanarak:
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")
EDIT: "Test" gibi durumlarda iyileştirilmesi için yer olduğunu görmek oldukça kolay olmalıdır, çünkü alt çizgi koşulsuz eklenir.
Sekmeyle ayrılmış bir dosyadaki başlıkları değiştirmek için yaptığım bir şey. Dosyanın sadece ilk satırını düzenlediğim bölümü atlıyorum. Yeniden kütüphaneyle Python'a kolayca adapte edebilirsiniz. Bu aynı zamanda sayıları ayırmayı da içerir (ancak rakamları bir arada tutar). İki adımda yaptım çünkü bir satırın veya sekmenin başına bir alt çizgi koymamayı söylemekten daha kolaydı.
Birinci Adım ... büyük harflerle başlayan büyük harfleri veya tam sayıları bulun ve önüne bir alt çizgi ekleyin:
Arama:
([a-z]+)([A-Z]|[0-9]+)
Değiştirme:
\1_\l\2/
İkinci Adım ... Yukarıdakileri alın ve tüm harfleri küçük harfe dönüştürmek için tekrar çalıştırın:
Arama:
([A-Z])
Değiştirme (ters eğik çizgi, küçük L, ters eğik çizgi, bir):
\l\1
Aynı soruna bir çözüm arıyordum, ancak bir zincire ihtiyacım vardı; Örneğin
"CamelCamelCamelCase" -> "Camel-camel-camel-case"
Buradaki iki kelimelik güzel çözümlerden başlayarak aşağıdakileri buldum:
"-".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"))
Karmaşık mantığın çoğu, ilk kelimeyi küçük harflerden kaçınmaktır. İlk kelimeyi değiştirmenin sakıncası yoksa daha basit bir sürüm:
"-".join(x.group(1).lower() for x in re.finditer("(^[^A-Z]+|[A-Z][^A-Z]+)", "stringToSplit"))
Elbette, diğer çözümlerde tartışıldığı gibi normal ifadeleri önceden derleyebilir veya kısa çizgi yerine alt çizgi ile birleştirebilirsiniz.
Düzenli ifadeler olmadan, ancak HTTPResponseCode => httpresponse_code:
def from_camel(name):
"""
ThisIsCamelCase ==> this_is_camel_case
"""
name = name.replace("_", "")
_cas = lambda _x : [_i.isupper() for _i in _x]
seq = zip(_cas(name[1:-1]), _cas(name[2:]))
ss = [_x + 1 for _x, (_i, _j) in enumerate(seq) if (_i, _j) == (False, True)]
return "".join([ch + "_" if _x in ss else ch for _x, ch in numerate(name.lower())])
Herhangi bir kütüphane olmadan:
def camelify(out):
return (''.join(["_"+x.lower() if i<len(out)-1 and x.isupper() and out[i+1].islower()
else x.lower()+"_" if i<len(out)-1 and x.islower() and out[i+1].isupper()
else x.lower() for i,x in enumerate(list(out))])).lstrip('_').replace('__','_')
Biraz ağır ama
CamelCamelCamelCase -> camel_camel_camel_case
HTTPRequest -> http_request
GetHTTPRequest -> get_http_request
getHTTPRequest -> get_http_request
Bu sitede önerilen çok güzel RegEx :
(?<!^)(?=[A-Z])
Python bir String Split yöntemi varsa, çalışması gerekir ...
Java dilinde:
String s = "loremIpsum";
words = s.split("(?<!^)(?=[A-Z])");
Birisinin tam bir kaynak dosyasını dönüştürmesi gerektiğinde, işte bunu yapacak bir komut dosyası vardır.
# 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))
Bu ile oldukça iyi şanslar oldu:
import re
def camelcase_to_underscore(s):
return re.sub(r'(^|[a-z])([A-Z])',
lambda m: '_'.join([i.lower() for i in m.groups() if i]),
s)
Bu tabii ki hız için bir optimize edilebilecek minik İstersen biraz.
import re
CC2US_RE = re.compile(r'(^|[a-z])([A-Z])')
def _replace(match):
return '_'.join([i.lower() for i in match.groups() if i])
def camelcase_to_underscores(s):
return CC2US_RE.sub(_replace, s)
: str.capitalize()
Dizesinin ilk harfini (str değişkeninde bulunur) büyük harfe dönüştürmek ve dizenin tamamını döndürmek için kullanın.
Örnek: Komut: "merhaba" .capitalize () Çıktı: Merhaba