Konwertuj na camelCase

34

Wyzwanie

Kiedyś czytałem Google Style Guide Google'a i potknąłem się o ich algorytm, aby przekonwertować dowolny ciąg znaków na notację camelCase. W tym wyzwaniu musisz wdrożyć ten algorytm, ponieważ nie chcesz robić tych wszystkich rzeczy w swojej głowie, gdy piszesz swoje super konkurencyjne zgłoszenia Java na wyzwania związane z golfem.

Uwaga: Wprowadziłem niewielkie poprawki w algorytmie. Musisz użyć tego określonego poniżej.

Algorytm

Zaczynasz od dowolnego ciągu wejściowego i stosujesz do niego następujące operacje:

  1. Usuń wszystkie apostrofy `'
  2. Podziel wynik na słowa, dzieląc na
    • znaki, które nie są alfanumeryczne i nie są cyframi [^a-zA-Z0-9]
    • Wielkie litery, które są otoczone małymi literami po obu stronach. abcDefGhI jkna przykład plonyabc Def Ghi jk
  3. Każde słowo ma małe litery.
  4. Wielka litera pierwszy znak każdego oprócz pierwszego słowa.
  5. Połącz wszystkie słowa z powrotem razem.

Dodatkowe uwagi

  • Dane wejściowe będą zawierać tylko ASCII do wydruku.
  • Jeśli cyfra jest pierwszą literą w słowie, pozostaw ją taką, jaka jest i nie zapisuj w tym słowie czegoś innego.
  • Dane wejściowe zawsze będą miały co najmniej jeden znak.

Zasady

Przypadki testowe

„Programowanie zagadek i golf” -> „programowanie PuzzleCodeGolf”
„Żądanie HTTP XML” -> „xmlHttpRequest”
„obsługuje IPv6 na iOS?” -> „obsługujeIpv6OnIos”
„SomeThing w1th, apo'strophe's i„ punc] tuation ”->„ someThingW1thApostrophesAndPuncTuation ”
„nic specjalnego” -> „nic specjalnego”
„5pecial ca5e” -> „5pecialCa5e”
„1337” -> „1337”
„1337-SPEk” -> „1337Speak”
„whatA mess” -> „whataMess”
„abcD” -> „abcd”
„a” -> „a”
„B” -> „b”

Happy Coding!

Denker
źródło
3
Co ciekawe, nigdy nie wiedziałem, że nazywa się to „camelCase”. Nazwa chyba pasuje ...
Ashwin Gupta
4
Jest więcej: snake_case&PascalCase
Martijn
14
@Martijn oczywiście z snake_casepowodu Pythona. FORTH też ma, FORTHCASEa APL maunreadable in any case
kot
Przypadek testowy 4 powinien mieć ApostropheSna wyjściu.
Tytus
@Tytus Nie, jest poprawny. Apostrofy są usuwane przed podziałem danych wejściowych.
Denker,

Odpowiedzi:

13

Siatkówka , 56 bajtów

Liczba bajtów zakłada kodowanie ISO 8859-1.

T`'\`
S_`\W|_|(?<=[a-z])(?=[A-Z][a-z])
T`L`l
T`l`L`¶.
¶

Wypróbuj online!

Wyjaśnienie

To implementuje specyfikację dosłownie:

T`'\`

Usuń apostrofy i wsteczne.

S_`\W|_|(?<=[a-z])(?=[A-Z][a-z])

Podziel ciąg wokół znaków innych niż słowa (w wyrażeniu regularnym wyklucza to również cyfry i znaki podkreślenia) lub podkreślenia lub pozycje, które mają małe litery po lewej stronie i wielkie litery, małe litery po prawej stronie. Spowodowałoby to utworzenie niektórych pustych segmentów, gdy w wierszu znajdują się dwa nieliterowe, niecyfrowe znaki lub, co ważniejsze, na początku łańcucha. Pozbywamy się tych z _opcją. Tutaj „podział” oznacza umieszczenie każdej pozostałej części na osobnej linii.

T`L`l

Konwertuj wszystko na małe litery.

T`l`L`¶.

Konwertuj każdy znak występujący po wysunięciu wiersza na wielkie litery. To wygodnie pominie pierwsze słowo, ponieważ przed nim nie ma linii.

Pozbądź się kanałów, aby połączyć wszystko z powrotem.

Martin Ender
źródło
Pobiłeś mnie do tego. Niezłe!
mbomb007
To pytanie może być trochę dziwne, ale ... czy powinienem opublikować swoją odpowiedź, jeśli jest krótsza niż twoje, a także w Retina? Pracowałem nad tym, zanim pojawiła się twoja odpowiedź, ale potem tak się stało i teraz nie wiem, czy powinienem to opublikować.
daavko
5
@daavko Jasne, opublikuj to (zazwyczaj decyduję na podstawie tego, jak różne jest podejście do istniejącej odpowiedzi ... jeśli jest to dokładnie to samo z bajtem wygolonym gdzieś, zwykle po prostu komentuję tę odpowiedź, ale jeśli jest ona znacznie krótsza innego podejścia, po prostu opublikuję osobną odpowiedź).
Martin Ender
2
@daavko Spojrzenie jest jednak konieczne. Pamiętaj, że twoja odpowiedź nie zachowuje wielkich liter, Thingchociaż powinna.
Martin Ender
1
@ MartinBüttner Oh ... Nie zauważyłem tego. No cóż, więc z powodzeniem odpowiem na inne wyzwanie.
daavko
11

Jawa, 198 190 bajtów

+3 bajty, ponieważ zapomniałem, że \W+==[^a-zA-Z0-9_]+ i muszę dopasować[^a-zA-Z0-9]+

-11 bajtów dzięki user20093 - ?:zamiastif /else

Ponieważ Java.

s->{String[]a=s.replaceAll("`|'","").split("[\\W_]+|(?<=[a-z])(?=[A-Z][a-z])");s="";for(String w:a){String t=w.toLowerCase();s+=a[0]==w?t:t.toUpperCase().charAt(0)+t.substring(1);}return s;}

To jest lambda. Zadzwoń tak:

UnaryOperator<String> op = s->{String[]a=s.replaceAll("`|'","").split("[\\W_]+|(?<=[a-z])(?=[A-Z][a-z])");s="";for(String w:a){String t=w.toLowerCase();s+=a[0]==w?t:t.toUpperCase().charAt(0)+t.substring(1);}return s;};
System.out.println(op.apply("Programming Puzzles & Code Golf"));

Wersja do odczytu:

public static String toCamelCase(String s) {
    String[] tokens = s
            .replaceAll("`|'", "") // 1. Remove all apostrophes
            .split("[\\W_]+|(?<=[a-z])(?=[A-Z][a-z])"); // 2. Split on [\W_]+ or between [a-z] and [A-Z][a-z]
    s = ""; // Reusing s for building output is cheap
    for (String token : tokens) {
        String lowercaseToken = token.toLowerCase(); // 3. Lowercase every word
        s += tokens[0].equals(token)?lowercaseToken:lowercaseToken.toUpperCase().charAt(0) + lowercaseToken.substring(1); // 4. Uppercase first char of all but first word
        // ^ 5. Join all words back together
    }
    return s;
}
CAD97
źródło
1
To nie jest Swift ...
CalculatorFeline
2
Witamy w Programowaniu Puzzle i Code Golf! To miła pierwsza odpowiedź!
Alex A.
1
@CatsAreFluffy What?
kot
jeśli
zastąpisz
Nie wiem, jak mi tego brakowało @ user902383 - dodano dla -11 bajtów. Niestety musiałem również dodać 3, aby dopasować _jako separator tokenów.
97 CAD
10

JavaScript (ES6), 156 154 152 148 145 141 140 bajtów

Dzięki @Neil (6 bajtów), @ETHproductions (3 bajty) i @ edc65 (7 bajtów)

a=>a[r='replace'](/`|'/g,a='')[r](/[a-z](?=[A-Z][a-z])/g,'$& ')[r](/[^\W_]+/g,b=>a+=(a?b[0].toUpperCase():'')+b.slice(!!a).toLowerCase())&&a

Usuwa apostrofy, następnie zastępuje, aby podzielić na znaki specjalne / przed otoczonymi wielkimi literami, a następnie łączy się z odpowiednią obudową. Niestety toLowerCase()i toUpperCase()są denerwująco długie i trudne do uniknięcia tutaj ...

Mwr247
źródło
1
Pracowałem nad innym podejściem, które twoje b.slice(i>0)podejście wydobywa z wody, ale w międzyczasie moje wyrażenie regularne /[A-Z]?([a-z0-9]|[0-9A-Z]{2,})+([A-Z](?![a-z]))?/gwydaje się zaoszczędzić 2 bajty nad twoim genialnym replacepodejściem.
Neil
1
Albo mógłbym po prostu zapisać 2 bajty replacebezpośrednio na twoim :replace(/[a-z](?=[A-Z][a-z])/g,'$& ')
Neil
1
Zwykle match...mapmożna go zastąpićreplace
edc65
1
@ edc65 Przy takim podejściu otrzymuję minimum 160 bajtów:a=>a.replace(/`|'/g,'').replace(/[a-z](?=[A-Z][a-z])/g,'$& ').replace(/[\W_]*([a-z0-9]+)[\W_]*/gi,(_,b,i)=>(i?b[0].toUpperCase():'')+b.slice(i>0).toLowerCase())
ETHproductions
2
Z drugiej strony chciałbym zaoferować, b=>a+=(a?b[0].toUpperCase():'')+b.slice(!!a).toLowerCase()co moim zdaniem pozwala zaoszczędzić kolejne 4 bajty.
Neil
7

vim, 69 68 66

:s/[`']//g<cr>:s/[a-z]\zs\ze[A-Z][a-z]\|\W\|_/\r/g<cr>o<esc>guggj<C-v>GgU:%s/\n<cr>

vim krótszy niż Perl ?! Co to za szaleństwo?

:s/[`']//g<cr>           remove ` and '
:s/                      match...
 [a-z]\zs\ze[A-Z][a-z]   right before a lowercase-surrounded uppercase letter
 \|\W\|_                 or a non-word char or underscore
 /\r/g<cr>               insert newlines between parts
o<esc>                   add an extra line at the end, necessary later...
gugg                     lowercasify everything
j                        go to line 2 (this is why we added the extra line)
<C-v>G                   visual select the first char of all-but-first line
gU                       uppercase
:%s/\n<cr>               join all lines into one

Dzięki Neil za wykrycie bezużytecznego naciśnięcia klawisza!

Klamka
źródło
Rozumiem, dlaczego to ostatnie :sma, %ale dlaczego niespójność w pierwszych dwóch?
Neil
@Neil Bah, pamięć mięśni. Dzięki!
Klamka
5
Udaje się być mniej czytelny niż Perl, a także +1
kot
Całkowicie
dodaję
1
@fruglemonkey 1. :%j<cr>jest równoważne i krótsze. 2. To dodaje spacje między wierszami.
Klamka
5

Mathematica 10.1, 101 bajtów

""<>(ToCamelCase@{##2}~Prepend~ToLowerCase@#&@@StringCases[StringDelete[#,"`"|"'"],WordCharacter..])&

Używa nieudokumentowanej ToCamelCase, która działa podobnie, Capitalizeale ustawia inne znaki na małe litery.

LegionMammal978
źródło
Nie w 10.3.0 ..
A Simmons
Jest ToCamelCase[n_,m_]:=n<>Capitalize/@mpoprawne? Wygląda jak to. A Prependpo co korzystać, gdy #~ToCamelCase~{##2}działa?
CalculatorFeline,
@CatsAreFluffy That daje miToCamelCase::argx: ToCamelCase called with 2 arguments; 1 argument is expected.
LegionMammal978
Jak działa CamelCase? Po prostu ToCamelCase[n_]:=""<>Capitalize/@n?
CalculatorFeline
@CatsAreFluffy, zobacz to .
LegionMammal978
5

Julia, 98 89 bajtów

s->lcfirst(join(map(ucfirst,split(replace(s,r"['`]",""),r"[a-z]\K(?=[A-Z][a-z])|\W|_"))))

Jest to anonimowa funkcja, która przyjmuje ciąg i zwraca ciąg. Aby go wywołać, przypisz go do zmiennej.

Podejście tutaj jest taka sama jak w klamce za Perl odpowiedziami : replaceapostrofy i backticks z pustym ciągiem, splitdo tablicy w sprawie wyrażenia regularnego, które pasuje do niezbędnych przypadków, funkcja na tablicy na wielkie pierwszą literę każdego elementu, z tyłu tablicy w ciąg, a wynik przekształca pierwszy znak na małe litery.mapucfirstjoinlcfirst

Alex A.
źródło
Zawsze lubiłem Julię jako bardziej funkcjonalnego, ciekawszego Pythona, ale nie znoszę endskładni. Może po prostu użyję anonimowych funkcji do wszystkiego, a potem nigdy nie będę musiał pisać end: D
cat
4

Perl 67 + 1 = 68 bajtów

y/'`//d;s/([a-z](?=[A-Z][a-z]))|\W|_/$1 /g;$_=lc;s/^ +| +(.)/\u$1/g

Wymaga -pflagi, a -ldla wielu linii:

$ perl -pl camelCase.pl input.txt
programmingPuzzlesCodeGolf
xmlHttpRequest
supportsIpv6OnIos:
someThingW1thApostrophesAndPuncTuation
nothingSpecial
5pecialCa5e
1337
1337Speak
abcd

Jak to działa:

y/'`//d;                            # Remove ' and `
s/([a-z](?=[A-Z][a-z]))|\W|_/$1 /g; # Replace according to '2. Split...' this will create
                                    #   a space separated string.
$_=lc;                              # lower case string
s/^ +| +(.)/\u$1/g                  # CamelCase the space separated string and remove any
                                    #   potential leading spaces.
andlrc
źródło
2

Perl, 87 80 78 bajtów

y/'`//d;$_=join'',map{ucfirst lc}split/[a-z]\K(?=[A-Z][a-z])|\W|_/,$_;lcfirst

Dodano bajt dla -pflagi.

Najpierw używamy y///operatora transliteracji, aby dusunąć wszystkie '`znaki z wejścia:

y/'`//d;

Następnie pojawia się treść kodu:

                         split/[a-z]\K(?=[A-Z][a-z])|\W|_/,$_;

(podziel ciąg wejściowy $_w odpowiednich miejscach, używając fantazyjnego \Kciągu dopasowania, aby wykluczyć część poprzedzającą go z rzeczywistego dopasowania)

          map{ucfirst lc}

(odwzoruj każdą podzieloną część łańcucha i spraw, aby cały łańcuch był pisany małymi literami, a następnie uczyń pierwszy znak zmodyfikowanego łańcucha dużymi literami)

$_=join'',

(dołącz do pustej struny i ponownie przypisz do magicznego podkreślenia $_, które zostanie wydrukowane na końcu)

Na koniec zmniejszamy pierwszą literę małymi literami, dopasowując ją\l do wyrażenia regularnego i używając ciągu zastępczego z wbudowanym, co pozwala zaoszczędzić 2 bajty w stosunku do poprzedniej metody:

lcfirst

Dzięki @ MartinBüttner za 7 bajtów ( [^a-zA-Z\d]-> \W|_)!

Klamka
źródło
1
Jak mu zazdroszczę \K...;)
Martin Ender
2

Lua, 127 bajtów

t=''l=t.lower z=io.read()for x in z:gmatch('%w+')do t=t..(t==''and l(x:sub(1,1))or x:sub(1,1):upper())..l(x:sub(2))end return t

Akceptuje ciąg ze standardowego wejścia i zwraca wyniki camelized.

Prawdopodobnie nadal będzie szukać lepszego rozwiązania, ponieważ przechowywanie wszystkiego w zmiennej wydaje się nieefektywne.

Ale w każdym razie całkiem proste:

 z:gmatch('%w+')

To piękno uratowało mi trochę bajtów. gmatch podzieli ciąg znaków na podstawie wzorca: %w+który przechwytuje tylko znaki alfanumeryczne.

Potem są to proste operacje na łańcuchach. string.upper, string.lower i gotowe.

Skyl3r
źródło
2

PHP, 145 122 133 bajtów

<?=join(split(" ",lcfirst(ucwords(strtolower(preg_replace(["#`|'#","#\W|_#","#([a-z])([A-Z][a-z])#"],[""," ","$1 $2"],$argv[1]))))));

Zapisz do pliku, zadzwoń z CLI.
Pobiera dane wejściowe z jednego argumentu wiersza poleceń; w razie potrzeby unikaj cudzysłowów i białych znaków.

awaria

<?=                 // 9. print result
join(split(" ",     // 8. remove spaces
    lcfirst(        // 7. lowercase first character
    ucwords(        // 6. uppercase first character in every word
    strtolower(     // 5. lowercase everything
    preg_replace(
        ["#`|'#",   "#\W|_#",   "#([a-z])([A-Z][a-z])#"],
        ["",        " ",        "$1 $2"],
        // 2. replace apostrophes with empty string (remove them)
                    // 3. replace non-word characters with space
                                // 4. insert space before solitude uppercase
        $argv[1]    // 1. take input from command line
    ))))
));

lcfirstpozwolono zredukować to do jednego polecenia, oszczędzając 23 bajty.
Naprawienie apostrofów kosztuje 11 bajtów dla dodatkowego przypadku zamiany.

Tytus
źródło
1

Kotlin , 160 bajtów

fun a(s: String)=s.replace(Regex("['`]"),"").split(Regex("[\\W_]+|(?<=[a-z])(?=[A-Z][a-z])")).map{it.toLowerCase().capitalize()}.joinToString("").decapitalize()

Moim celem była Scala, druga „alternatywna Java”, więc jestem trochę zadowolony z moich wyników. Ukradłem wyrażenie regularne z odpowiedzi Java .

Przetestuj za pomocą:

fun main(args: Array<String>) {
    val testCases = arrayOf(
            "Programming Puzzles & Code Golf",
            "XML HTTP request",
            "supports IPv6 on iOS?",
            "SomeThing w1th, apo'strophe's and' punc]tuation",
            "nothing special",
            "5pecial ca5e",
            "1337",
            "1337-spEAk",
            "abcD",
            "a",
            "B")
    testCases.forEach { println(a(it)) }

}
Nathan Merrill
źródło
W tym momencie myślę, że wszyscy „pożyczają” zoptymalizowane wyrażenie regularne \W|_|(?<=[a-z])(?=[A-Z][a-z])lub nieznacznie go modyfikują np. [\W_]+
97 CAD
możesz zapisać niektóre na mapie i funkcję rozszerzeniafun String.a()=replace(Regex("['`]"),"").split(Regex("[\\W_]+|(?<=[a-z])(?=[A-Z][a-z])")).joinToString(""){it.toLowerCase().capitalize()}.decapitalize()
możliwe
1

Scala, 181 170 144

def f(s:String)={val l=s.replaceAll("'|`","")split("[\\W_]+|(?<=[a-z])(?=[A-Z][a-z])")map(_.toLowerCase);l(0)+l.tail.map(_.capitalize).mkString}

Próbnik:

val testCases = List(
  "Programming Puzzles & Code Golf" -> "programmingPuzzlesCodeGolf",
  "XML HTTP request" -> "xmlHttpRequest"
  // etc
)
println(testCases.map(t=>if(t._2!=f(t._1))s"FAIL:${f(t._1)}"else"PASS").mkString("\n"))

Rekwizyty do CAD97 i przeprosiny dla Nathana Merrilla :)

polana
źródło
1
Możesz zapisać 6 bajtów, zastępując [^a-zA-Z0-9]+je [\\W_]+.
97 CAD
0

C 272 znaków

Program C przekazuje ciąg znaków do camelCase w cudzysłowach jako argument 1. W opisie problemu jest wiele gotchas ...

#define S strlen(t)
#define A isalnum(t[i])
j=0;main(i,v)char**v;{char*p=v[1],*t;char o[99]={0};while(t=strtok(p," [{(~!@#$%^*-+=)}]")){i=0;p+=S+1;while((!A)&&i<S)i++;if(i!=S){o[j]=((j++==0)?tolower(t[i++]):toupper(t[i++]));while(i<S){if(A)o[j++]=t[i];i++;}}}puts(o);}
cleblanc
źródło
Trzeba #include<string.h>za strlen, strtoki toupper, i #include<ctype.h>dla isalnum.
Mego
Nie potrzebowałem go za pomocą gcc 3.4.4 w cygwin. Muszą one zostać automatycznie połączone, przy założeniu extern int.
cleblanc
Z ./camel "Programming Puzzles & Code Golf"cygwin (skompilowany z gcc 3.4.4), dostaję programmingPuzzlesCodeEGolf. Ta sama wydajność z 5.3.0.
Mego
Bzdury. Ja też. Musiałem stworzyć błąd podczas gry w golfa. Patrzę na to teraz ...
cleblanc
Problem polegał na tym, że dodałem inne łańcuchy tokenizera po grze w golfa i nie przetestowałem go wystarczająco dobrze. Jeśli usuniesz „&” z wywołania strtok, zadziała na tym wejściu.
cleblanc
0

JavaScript, 123 bajty

v=>v[r="replace"](/[`']/g,"")[r](/^.|.$|[A-Z][^a-z]+/g,x=>x.toLowerCase())[r](/[^a-z0-9]+./ig,x=>x.slice(-1).toUpperCase())

Wersja do odczytu

v=>
  v.replace(/[`']/g,"")
  .replace(/^.|.$|[A-Z][^a-z]+/g,x=>x.toLowerCase())
  .replace(/[^a-z0-9]+./ig,x=>x.slice(-1).toUpperCase())

Usuń apostrofy, umieść pierwszy znak małymi literami, ostatni znak małymi literami i dowolną grupę wielu wielkich liter, dopasuj dowolną grupę 1 lub więcej znaków niealfanumerycznych + 1 inny znak, zamień na ostatni znak wielkimi literami.

[r = "replace"] trick z rozwiązania Mrw247.

Grax32
źródło