CamelCase2snake_case ()

13

Schreiben Sie eine Funktion, um CamelCased-Text in snake_case umzuwandeln: FunctionForHTMLManipulationwirdfunction_for_html_manipulation

Der Eingabetext ist in vielen Sprachen eine geeignete Kennung. Es muss mit einem englischen Buchstaben beginnen, gefolgt von einer beliebigen Anzahl englischer Buchstaben oder Ziffern. Andere Zeichen (Leerzeichen, Symbole usw.) sind nicht zulässig.

Jedes "Wort" im CamelCased-Text beginnt mit einem Großbuchstaben, es sei denn, am Anfang des Textes oder unmittelbar nach einer Ziffer, gefolgt von null oder mehr Buchstaben in der gleichen Groß- / Kleinschreibung. Zifferngruppen werden als separate Wörter betrachtet, aber unverändert weitergeleitet.

Mit anderen Worten, ein Kleinbuchstabe, gefolgt von einem Großbuchstaben, weist auf einen Wortumbruch hin. Alle Buchstaben und Ziffern nebeneinander bedeuten einen Wortumbruch. Ein Großbuchstabe, gefolgt von einem anderen Großbuchstaben und einem Kleinbuchstaben, weist auf einen Wortumbruch hin.

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

Beides Buy24Beersund buy24beerswerden buy_24_beers.
MacDonaldAndObrianwird mac_donald_and_obrian.
MACDonaldAndOBrianwird mac_donald_and_o_brian.

CJ Dennis
quelle
6
" MACDonaldAndOBrianwird mac_donald_and_o_brian" - warum?
Qwertiy
2
@Qwertiy Weil ich dachte, diese Namen würden Spaß machen. Es sei denn, Sie fragen nach der Regel, die von ...UUl...=> abgedeckt wird ...u_ul....
CJ Dennis
Sehr eng verwandt
Digital Trauma
@DigitalTrauma Erstaunlich nah an meiner ursprünglichen Frage, aber ohne die Beschwerden, dass es zwei Fragen in einer und keine Abstimmungen gibt! Der größte Unterschied besteht in der Behandlung von ALLCAPS-Saiten. Ich habe gesucht, um zu sehen, ob die Frage schon einmal gestellt wurde, aber ich habe sie nicht gefunden.
CJ Dennis
1
@ggorlen das ...zeigt an, dass es sich in der Mitte eines Strings befindet.
CJ Dennis

Antworten:

7

Retina , 61 37 Bytes

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

Probieren Sie es online! (Leicht modifiziert, um eine vollständige Testsuite auszuführen.)

Erläuterung

Anstatt Wortgrenzen zum Einfügen von Unterstrichen zu finden, passen wir einfach jedes Wort an und stellen a voran _. Das Übereinstimmen von Wörtern von links ist aufgrund der UUlRegel etwas ärgerlich , aber mit dem von rechts nach links passenden .NET können wir Wörter leicht gierig zuordnen. Um eine Führung zu vermeiden _, nutzen wir die Grenzen von Retina.

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

Der raktiviert den Rechts-Links-Modus und 1>weist Retina an, alles außer der ersten Übereinstimmung zu verarbeiten (von links nach rechts zu zählen). Dann gibt es vier Arten von „Wörtern“: Ulll, lll, UUU, ddd. Diese lassen sich leicht mit dem vorgegebenen Muster abgleichen. Die Ersetzung schreibt nur ein _gefolgt von dem Wort selbst.

T`L`l

Dadurch wird Groß- und Kleinschreibung einfach in Kleinschreibung umgewandelt, um die Umwandlung abzuschließen.

Martin Ender
quelle
6

JavaScript (ES6), 79 Byte

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

JavaScript (ES6), 89 Byte

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

Powershell, 77 Bytes

Basierend auf Neils Antwort .

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

Weniger Golf-Testskript:

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

Ausgabe:

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

PowerShell, 68 bis 92 Byte

Kurz gelöscht, +24 Bytes für die Verwendung des falschen RegEx.

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

Probieren Sie es online!

Grundsätzlich die gleichen wie die JavaScript-Lösungen.

Gabriel Mills
quelle
Es funktioniert nicht mit buy24beersund MACDonaldAndOBrian. Es tut uns leid.
mazzy
1
@mazzy behoben, danke.
Gabriel Mills
0

Faktor 140 Byte

[ 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 ;
Katze
quelle
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

Probieren Sie es online!

Diese Lösung profitiert von Luas Kurzschreibweise für die Zeichenklassen von C (Kleinbuchstaben %l, Großbuchstaben %u, Buchstaben %a, Ziffern %d), der Grenzschreibweise ( %f[]) und davon, dass die gesamte Übereinstimmung als implizite erste Erfassung hinzugefügt wird, wenn keine anderen Erfassungen vorhanden sind.

Cyclaminist
quelle