CamelCase2snake_case ()

13

Napisz funkcję do konwersji tekstu CamelCased na snake_case: FunctionForHTMLManipulationstaje sięfunction_for_html_manipulation

Tekst wejściowy będzie jednym odpowiednim identyfikatorem w wielu językach. Musi zaczynać się literą angielską, a następnie dowolną liczbą liter lub cyfr angielskich. Żadne inne znaki (spacje, symbole itp.) Są niedozwolone.

Każde „słowo” w tekście Wielbłąda zaczyna się wielką literą, chyba że na początku tekstu lub bezpośrednio po cyfrze, a po nim następuje zero lub więcej liter, w tym samym przypadku. Grupy cyfr będą traktowane jako osobne słowa, ale przejdą bez zmian.

Innymi słowy, mała litera, po której następuje wielka litera, oznacza podział wyrazu. Każda litera i cyfra obok siebie oznacza podział słowa. Wielka litera, po której następuje kolejna wielka litera i mała litera oznaczają podział wyrazu.

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

Obaj Buy24Beersi buy24beerszostańcie buy_24_beers.
MacDonaldAndObrianstaje się mac_donald_and_obrian.
MACDonaldAndOBrianstaje się mac_donald_and_o_brian.

CJ Dennis
źródło
6
MACDonaldAndOBrianstaje się mac_donald_and_o_brian - dlaczego?
Qwertiy
2
@Qwertiy Ponieważ myślałem, że te imiona będą fajne. Chyba że pytasz o regułę, która jest objęta ...UUl...=> ...u_ul....
CJ Dennis
@DigitalTrauma Zadziwiająco blisko do mojego pierwotnego pytania, ale bez skarg na bycie dwoma pytaniami w jednym i brak głosów negatywnych! Największa różnica polega na traktowaniu ciągów ALLCAPS. Szukałem, czy pytanie zostało zadane wcześniej, ale go nie znalazłem.
CJ Dennis,
1
@gorgor ...wskazuje, że jest w środku łańcucha.
CJ Dennis,

Odpowiedzi:

7

Retina , 61 37 bajtów

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

Wypróbuj online! (Nieznacznie zmodyfikowany, aby uruchomić pełny zestaw testów).

Wyjaśnienie

Zamiast znajdować granice słów do wstawienia znaków podkreślenia, po prostu dopasowujemy każde słowo i poprzedzamy je znakiem _. Dopasowywanie słów z lewej strony jest nieco denerwujące z powodu UUlreguły, ale przy użyciu dopasowania .NET od prawej do lewej możemy łatwo dopasować słowa łapczywie. Aby uniknąć prowadzenia _, korzystamy z limitów Retiny.

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

rAktywuje tryb prawej do lewej, 1>mówi siatkówka do procesu wszystko z wyjątkiem pierwszego meczu (licząc od lewej do prawej). Wtedy tam cztery rodzaje „słów”: Ulll, lll, UUU, ddd. Można je łatwo dopasować do podanego wzoru. Podstawienie po prostu pisze _po nim samo słowo.

T`L`l

To po prostu zamienia wielkie litery na małe, aby zakończyć transformację.

Martin Ender
źródło
6

JavaScript (ES6), 79 bajtów

s=>s.match(/[A-Z]+(?=[A-Z][a-z]|\d|$)|[A-Z]?[a-z]+|\d+/g).join`_`.toLowerCase()
użytkownik 81655
źródło
3

JavaScript (ES6), 89 bajtów

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

PowerShell, 77 bajtów

Na podstawie odpowiedzi Neila .

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

Skrypt testu mniej golfowego:

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

Wynik:

True: buy_24_beers
True: buy_24_beers
True: mac_donald_and_obrian
True: mac_donald_and_o_brian
True: big_d
mazzy
źródło
1

PowerShell, 68 92 bajtów

Krótko usunięte, +24 bajty za użycie niewłaściwego RegEx.

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

Wypróbuj online!

Zasadniczo to samo, co rozwiązania JavaScript.

Gabriel Mills
źródło
Nie działa z buy24beersi MACDonaldAndOBrian. Przepraszam.
mazzy
1
@mazzy naprawione, dzięki.
Gabriel Mills,
0

Współczynnik, 140 bajtów

[ 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 ]

Nie golfowany:

: 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 ;
kot
źródło
0

Lua , 135 bajtów

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

Wypróbuj online!

To rozwiązanie korzysta ze skróconej notacji Lua dla klas znaków C (małe litery %l, wielkie litery %u, alfabet %a, cyfra %d), notacji na granicy ( %f[]), a także z dodania całego dopasowania jako domyślnego pierwszego przechwytywania przy braku innych przechwyceń.

cyklista
źródło