CamelCase2snake_case ()

13

Escreva uma função para converter o texto CamelCased em snake_case: FunctionForHTMLManipulationtorna - sefunction_for_html_manipulation

O texto de entrada será um único identificador adequado em vários idiomas. Ele deve começar com uma letra em inglês e, em seguida, ser seguido por qualquer número de letras ou dígitos em inglês. Nenhum outro caractere (espaços, símbolos, etc.) é permitido.

Cada "palavra" no texto do CamelCased começará com uma letra maiúscula, a menos que no início do texto ou imediatamente após um dígito, e seja seguida por zero ou mais letras, todos no mesmo caso. Grupos de dígitos serão considerados como palavras separadas, mas passarão inalterados.

Em outras palavras, uma letra minúscula seguida por uma letra maiúscula indica uma quebra de palavra. Qualquer letra e dígito próximos um do outro indica uma quebra de palavra. Uma letra maiúscula seguida por outra letra maiúscula e uma letra minúscula indica uma quebra de palavra.

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

Ambos Buy24Beerse buy24beersse tornam buy_24_beers.
MacDonaldAndObriantorna-se mac_donald_and_obrian.
MACDonaldAndOBriantorna-se mac_donald_and_o_brian.

CJ Dennis
fonte
6
" MACDonaldAndOBriantorna-se mac_donald_and_o_brian" - por quê?
precisa saber é o seguinte
2
@ Qwertiy Porque eu pensei que esses nomes seriam divertidos. A menos que você esteja perguntando sobre a regra, que é coberta por ...UUl...=> ...u_ul....
CJ Dennis
Muito próximo
Digital Trauma
@DigitalTrauma Surpreendentemente perto da minha pergunta original, mas sem as queixas de ser duas perguntas em uma e sem votos negativos! A maior diferença está no tratamento de cadeias ALLCAPS. Procurei se a pergunta já havia sido feita antes, mas não a encontrei.
CJ Dennis
1
@ggorlen o ...indica que está no meio de uma string.
CJ Dennis

Respostas:

7

Retina , 61 37 bytes

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

Experimente online! (Ligeiramente modificado para executar um conjunto de testes completo.)

Explicação

Em vez de encontrar limites de palavras para inserir sublinhados, simplesmente combinamos cada palavra e adicionamos um a _. A correspondência de palavras da esquerda é um pouco irritante por causa da UUlregra, mas, usando a correspondência da direita para a esquerda do .NET, podemos facilmente corresponder as palavras com avidez. Para evitar a liderança _, usamos os limites da Retina.

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

A rativa o modo da direita para a esquerda, a 1>conta Retina para o processo de tudo, exceto o primeiro jogo (contagem da esquerda para a direita). Depois, há quatro tipos de "palavras": Ulll, lll, UUU, ddd. Eles são facilmente compatíveis com o padrão fornecido. A substituição apenas escreve um _seguido pela própria palavra.

T`L`l

Isso simplesmente transforma maiúsculas em minúsculas para concluir a transformação.

Martin Ender
fonte
6

JavaScript (ES6), 79 bytes

s=>s.match(/[A-Z]+(?=[A-Z][a-z]|\d|$)|[A-Z]?[a-z]+|\d+/g).join`_`.toLowerCase()
user81655
fonte
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
fonte
2

Powershell, 77 bytes

Baseado na resposta de Neil .

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

Script de teste com menos golfe:

$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"
}

Resultado:

True: buy_24_beers
True: buy_24_beers
True: mac_donald_and_obrian
True: mac_donald_and_o_brian
True: big_d
confuso
fonte
1

PowerShell, 68 92 bytes

Excluídos brevemente, +24 bytes por usar o RegEx errado.

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

Experimente online!

Basicamente, o mesmo que as soluções JavaScript.

Gabriel Mills
fonte
Não funciona com buy24beerse MACDonaldAndOBrian. Desculpe.
Mazzy
1
@mazzy corrigido, obrigado.
Gabriel Mills
0

Fator, 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 ]

Ungolfed:

: 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
fonte
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

Experimente online!

Esta solução se beneficia da notação abreviada de Lua para as classes de caracteres de C (minúscula %l, maiúscula %u, alfabética %a, dígito %d), notação de fronteira ( %f[]) e de toda a correspondência sendo adicionada como a primeira captura implícita na ausência de outras capturas.

ciclaminista
fonte