CamelCase2snake_case ()

13

Escriba una función para convertir texto CamelCased a snake_case: se FunctionForHTMLManipulationconviertefunction_for_html_manipulation

El texto de entrada será un único identificador adecuado en muchos idiomas. Debe comenzar con una letra en inglés, luego debe seguir cualquier número de letras o dígitos en inglés. No se permiten otros caracteres (espacios, símbolos, etc.).

Cada "palabra" dentro del texto CamelCased comenzará con una letra mayúscula a menos que sea al comienzo del texto o inmediatamente después de un dígito, y será seguida por cero o más letras, todas en el mismo caso. Los grupos de dígitos se considerarán como palabras separadas pero pasarán sin cambios.

En otras palabras, una letra minúscula seguida de una letra mayúscula indica un salto de palabra. Cualquier letra y dígito uno al lado del otro indica un salto de palabra. Una letra mayúscula seguida de otra letra mayúscula y una letra minúscula indican un salto de palabra.

...lU...=> ...l_u...
...l9...=> ...l_9...
...U9...=> ...u_9...
...9l...=> ...9_l...
...9U...=> ...9_u...
...UUl...=>...u_ul...

Ambos Buy24Beersy buy24beersconvertirse buy_24_beers.
MacDonaldAndObrianse convierte mac_donald_and_obrian.
MACDonaldAndOBrianse convierte mac_donald_and_o_brian.

CJ Dennis
fuente
66
"se MACDonaldAndOBrianconvierte mac_donald_and_o_brian" - ¿por qué?
Qwertiy
2
@Qwertiy Porque pensé que esos nombres serían divertidos. A menos que pregunte sobre la regla, que está cubierta por ...UUl...=> ...u_ul....
CJ Dennis
@DigitalTrauma ¡Increíblemente cercano a mi pregunta original pero sin las quejas de ser dos preguntas en una y sin votos negativos! La mayor diferencia está en el tratamiento de las cadenas ALLCAPS. Busqué para ver si la pregunta se había hecho antes, pero no la encontré.
CJ Dennis el
1
@ggorlen ...indica que está en el medio de una cadena.
CJ Dennis

Respuestas:

7

Retina , 61 37 bytes

r1>`[A-Z]?[a-z]+|[A-Z]+|\d+
_$&
T`L`l

Pruébalo en línea! (Ligeramente modificado para ejecutar un conjunto de pruebas completo).

Explicación

En lugar de encontrar límites de palabras para insertar guiones bajos, simplemente hacemos coincidir cada palabra y anteponemos a _. Coincidir palabras desde la izquierda es un poco molesto debido a la UUlregla, pero usando la correspondencia de derecha a izquierda de .NET podemos unir fácilmente las palabras con avidez. Para evitar una ventaja _, hacemos uso de los límites de Retina.

r1>`[A-Z]?[a-z]+|[A-Z]+|\d+
_$&

La ractiva el modo de derecha a izquierda, el 1>dice Retina de proceso de todo excepto el primer partido (conteo de izquierda a derecha). Entonces hay cuatro tipos de "palabras": Ulll, lll, UUU, ddd. Estos se combinan fácilmente con el patrón dado. La sustitución solo escribe un _seguido por la palabra misma.

T`L`l

Esto simplemente convierte mayúsculas en minúsculas para completar la transformación.

Martin Ender
fuente
6

JavaScript (ES6), 79 bytes

s=>s.match(/[A-Z]+(?=[A-Z][a-z]|\d|$)|[A-Z]?[a-z]+|\d+/g).join`_`.toLowerCase()
usuario81655
fuente
3

JavaScript (ES6), 89 bytes

s=>s.replace(/\d(?=\D)|\D(?=\d)|[a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z])/g,"$&_").toL‌​owerCase()
Neil
fuente
2

Powershell, 77 bytes

Basado en la respuesta de Neil .

$args-creplace'\d(?=\D)|\D(?=\d)|[a-z](?=[A-Z])|.(?=[A-Z][a-z])','$&_'|% *wer

Menos guión de prueba de golf:

$f = {

$args-creplace'\d(?=\D)|\D(?=\d)|[a-z](?=[A-Z])|.(?=[A-Z][a-z])','$&_'|% toLower

}

@(
    ,("Buy24Beers", "buy_24_beers")
    ,("buy24beers", "buy_24_beers")
    ,("MacDonaldAndObrian", "mac_donald_and_obrian")
    ,("MACDonaldAndOBrian", "mac_donald_and_o_brian")
    ,("BigD", "big_d")
) | % {
    $s,$expected = $_
    $result = &$f $s
    "$($result-ceq$expected): $result"
}

Salida:

True: buy_24_beers
True: buy_24_beers
True: mac_donald_and_obrian
True: mac_donald_and_o_brian
True: big_d
mazzy
fuente
1

PowerShell, 68 92 bytes

Brevemente eliminado, +24 bytes por usar el RegEx incorrecto.

($args-creplace'\d(?=\D)|\D(?=\d)|[a-z](?=[A-Z])|.(?=[A-Z][a-z])','$&_').Trim('_').ToLower()

Pruébalo en línea!

Básicamente lo mismo que las soluciones de JavaScript.

Gabriel Mills
fuente
No funciona con buy24beersy MACDonaldAndOBrian. Lo siento.
mazzy
1
@mazzy arreglado, gracias.
Gabriel Mills el
0

Factor, 140 bytes

[ R/ [a-z][A-Z][a-z]/ [ dup from>> swap dup to>> swap seq>> subseq R/ [A-Z][a-z]/ [ "_" prepend ] re-replace-with ] re-replace-with >lower ]

Sin golf:

: slice>subseq ( slice -- subseq )
dup from>> swap dup to>> swap seq>> subseq ;

: camel-case>snake-case ( string -- string' )
    R/ [a-z][A-Z][a-z]/ [
        slice>subseq R/ [A-Z][a-z]/
        [ "_" prepend ] re-replace-with
    ] re-replace-with >lower ;
gato
fuente
0

Lua , 135 bytes

function snake(s)return s:gsub('%f[^%l]%u','_%1'):gsub('%f[^%a]%d','_%1'):gsub('%f[^%d]%a','_%1'):gsub('(%u)(%u%l)','%1_%2'):lower()end

Pruébalo en línea!

Esta solución se beneficia de la notación abreviada de Lua para las clases de caracteres de C (minúscula %l, mayúscula %u, alfabético %a, dígito %d), notación de frontera ( %f[]) y de que toda la coincidencia se agrega como la primera captura implícita en ausencia de otras capturas.

ciclaminista
fuente