variable underscore style snake_case snake español camelcase python camelcasing

underscore - snake case naming style python



¿Elegante función de Python para convertir CamelCase a snake_case? (30)

Aquí está mi solución:

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)

Es compatible con los casos de esquina discutidos en los comentarios. Por ejemplo, convertirá getHTTPResponseCode en get_http_response_code como debería.

Ejemplo:

>>> convert(''CamelCase'') ''camel_case''


Aquí hay algo que hice para cambiar los encabezados en un archivo delimitado por tabulaciones. Estoy omitiendo la parte donde solo edité la primera línea del archivo. Podrías adaptarlo a Python fácilmente con la biblioteca re. Esto también incluye separar números (pero mantiene los dígitos juntos). Lo hice en dos pasos porque era más fácil que decirle que no pusiera un guión bajo al comienzo de una línea o pestaña.

Paso uno ... encuentra letras mayúsculas o enteros precedidos por letras minúsculas, y precede con un guión bajo:

Buscar:

([a-z]+)([A-Z]|[0-9]+)

Reemplazo:

/1_/l/2/

Paso dos ... toma lo anterior y ejecútalo de nuevo para convertir todas las mayúsculas a minúsculas:

Buscar:

([A-Z])

Reemplazo (es barra diagonal inversa, L minúscula, barra diagonal inversa, una):

/l/1


Conciso sin expresiones regulares, pero 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())])


Creo que esta solución es más directa que las respuestas anteriores:

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))

Qué salidas:

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

La expresión regular coincide con tres patrones:

  1. [AZ]?[az]+ : minúsculas consecutivas que, opcionalmente, comienzan con una letra mayúscula.
  2. [AZ]{2,}(?=[AZ][az]|/d|/W|$) : dos o más letras mayúsculas consecutivas. Utiliza un lookahead para excluir la última letra mayúscula si va seguida de una letra minúscula.
  3. /d+ : Números consecutivos.

Al usar re.findall obtenemos una lista de "palabras" individuales que se pueden convertir a minúsculas y unirlas con guiones bajos.


Echa un vistazo a la excelente libreta de esquemas.

https://github.com/schematics/schematics

Le permite crear estructuras de datos escritas que pueden serializar / deserializar desde Python a Javascript, por ejemplo:

class MapPrice(Model): price_before_vat = DecimalType(serialized_name=''priceBeforeVat'') vat_rate = DecimalType(serialized_name=''vatRate'') vat = DecimalType() total_price = DecimalType(serialized_name=''totalPrice'')


El uso de expresiones regulares puede ser el más corto, pero esta solución es mucho más legible:

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


En caso de que alguien necesite transformar un archivo fuente completo, aquí hay un script que lo hará.

# 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))


Estaba buscando una solución al mismo problema, excepto que necesitaba una cadena; p.ej

"CamelCamelCamelCase" -> "Camel-camel-camel-case"

Partiendo de las bonitas soluciones de dos palabras aquí, se me ocurrió lo siguiente:

"-".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"))

La mayor parte de la lógica complicada es evitar minúsculas en la primera palabra. Aquí hay una versión más simple si no te importa alterar la primera palabra:

"-".join(x.group(1).lower() for x in re.finditer("(^[^A-Z]+|[A-Z][^A-Z]+)", "stringToSplit"))

Por supuesto, puede precompilar las expresiones regulares o unirse con un guión bajo en lugar de un guión, como se explica en las otras soluciones.


Este método simple debe hacer el trabajo:

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()

  • Buscamos letras mayúsculas que están precedidas por cualquier número de letras mayúsculas (o cero), y seguidas por cualquier número de caracteres en minúscula.
  • Un guión bajo se coloca justo antes de que aparezca la última letra mayúscula encontrada en el grupo, y uno se puede colocar antes de esa letra mayúscula en caso de que esté precedido por otras letras mayúsculas.
  • Si hay guiones bajos, quítalos.
  • Finalmente, toda la cadena de resultados se cambia a minúsculas.

(tomado de here , ver ejemplo de trabajo en línea )


Este no es un método elegante, es una implementación de muy bajo nivel de una máquina de estado simple (máquina de estado de campo de bits), posiblemente el modo más antipónico para resolver esto, sin embargo, el módulo también implementa una máquina de estado demasiado compleja para resolver este sencillo Tarea, entonces creo que esta es una buena solución.

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 puede analizar todos los tipos de casos: UpperSEQUENCEInterleaved, under_score, BIG_SYMBOLS y cammelCasedMethods

Espero que sea útil


Esto es bastante minucioso:

def convert(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()

Funciona con todos estos (y no daña las versiones que ya han sido desbloqueadas):

>>> convert(''CamelCase'') ''camel_case'' >>> convert(''CamelCamelCase'') ''camel_camel_case'' >>> convert(''Camel2Camel2Case'') ''camel2_camel2_case'' >>> convert(''getHTTPResponseCode'') ''get_http_response_code'' >>> convert(''get2HTTPResponseCode'') ''get2_http_response_code'' >>> convert(''HTTPResponseCode'') ''http_response_code'' >>> convert(''HTTPResponseCodeXYZ'') ''http_response_code_xyz''

O si lo vas a llamar un millón de veces, puedes precompilar las expresiones regulares:

first_cap_re = re.compile(''(.)([A-Z][a-z]+)'') all_cap_re = re.compile(''([a-z0-9])([A-Z])'') def convert(name): s1 = first_cap_re.sub(r''/1_/2'', name) return all_cap_re.sub(r''/1_/2'', s1).lower()

No olvides importar el módulo de expresiones regulares.

import re



He tenido bastante buena suerte con este:

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)

Obviamente, esto podría optimizarse para la velocidad un poco si lo desea.

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)


Ligeramente adaptado de https://.com/users/267781/matth que usan generadores.

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()


Muy bonito RegEx propuesto en este sitio :

(?<!^)(?=[A-Z])

Si Python tiene un método de división de cadenas, debería funcionar ...

En Java:

String s = "loremIpsum"; words = s.split("(?&#60;!^)(?=[A-Z])");



No sé por qué todo esto es tan complicado.

para la mayoría de los casos, la expresión simple ([AZ]+) hará el truco

>>> 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''

Para ignorar el primer personaje, simplemente agregue look behind (?!^)

>>> 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''

Si desea separar ALLCaps a all_caps y esperar números en su cadena, todavía no necesita hacer dos ejecuciones separadas solo use | Esta expresión ((?<=[a-z0-9])[AZ]|(?!^)[AZ](?=[az])) puede manejar casi todos los escenarios del libro

>>> 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''

Todo depende de lo que desee, así que use la solución que mejor se adapte a sus necesidades, ya que no debería ser demasiado complicada.

nJoy!


No tengo idea de por qué usar ambas llamadas .sub ()? :) No soy un experto en expresiones regulares, pero simplifiqué la función a esta, que es adecuada para mis necesidades específicas, solo necesitaba una solución para convertir camelCasedVars de la solicitud POST a vars_with_underscore:

def myFunc(...): return re.sub(''(.)([A-Z]{1})'', r''/1_/2'', "iTriedToWriteNicely").lower()

No funciona con nombres como getHTTPResponse, porque escuché que es una mala convención de nomenclatura (debería ser como getHttpResponse, obviamente es que es mucho más fácil memorizar este formulario).


Personalmente, no estoy seguro de cómo cualquier cosa que use expresiones regulares en python pueda ser descrita como elegante. La mayoría de las respuestas aquí solo hacen trucos RE de "código de golf". La codificación elegante se supone que es fácil de entender.

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''


Prefiero evitar re si es posible:

myString="ThisStringIsCamelCase" ''''.join([''_''+i.lower() if i.isupper() else i for i in myString]).lstrip(''_'') ''this_string_is_camel_case''


Sin ninguna biblioteca:

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(''__'',''_'')

Un poco pesado, pero

CamelCamelCamelCase -> camel_camel_camel_case HTTPRequest -> http_request GetHTTPRequest -> get_http_request getHTTPRequest -> get_http_request


Tantos métodos complicados ... Simplemente encuentre todo el grupo "Titulado" y únase a su variante de caja inferior con un guión bajo.

>>> 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''

Si no desea hacer números como el primer carácter del grupo o grupo separado, puede usar la máscara ([Az][a-z0-9]*) .


Un ejemplo horrendo usando expresiones regulares (puedes limpiar esto fácilmente :)):

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")

Funciona para getHTTPResponseCode sin embargo!

Alternativamente, usando 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")

EDITAR: También debería ser bastante fácil ver que hay espacio para mejoras en casos como "Prueba", porque el guión bajo se inserta incondicionalmente.


Use: str.capitalize() para convertir la primera letra de la cadena (contenida en la variable str) en una letra mayúscula y devuelve la cadena completa.

Ejemplo: Comando: "hello" .capitalize () Salida: Hello


Wow, acabo de robar esto de fragmentos de Django. ref http://djangosnippets.org/snippets/585/

Bastante elegante

camelcase_to_underscore = lambda str: re.sub(''(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))'', ''_//1'', str).lower().strip(''_'')

Ejemplo:

camelcase_to_underscore(''ThisUser'')

Devoluciones:

''this_user''


stringcase es mi biblioteca para esto; p.ej:

>>> from stringcase import pascalcase, snakecase >>> snakecase(''FooBarBaz'') ''foo_bar_baz'' >>> pascalcase(''foo_bar_baz'') ''FooBarBaz''


Por el gusto de hacerlo:

>>> 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''

O, más por diversión.

>>> 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''


''''.join(''_''+c.lower() if c.isupper() else c for c in "DeathToCamelCase").strip(''_'') re.sub("(.)([A-Z])", r''/1_/2'', ''DeathToCamelCase'').lower()


def convert(camel_str): temp_list = [] for letter in camel_str: if letter.islower(): temp_list.append(letter) else: temp_list.append(''_'') temp_list.append(letter) result = "".join(temp_list) return result.lower()


def convert(name): return reduce( lambda x, y: x + (''_'' if y.isupper() else '''') + y, name ).lower()

Y si necesitamos cubrir un caso con una entrada que ya no está disponible:

def convert(name): return reduce( lambda x, y: x + (''_'' if y.isupper() and not x.endswith(''_'') else '''') + y, name ).lower()