CamelCase'e dönüştür


34

Meydan okuma

Geçen gün Google’ın Java Stil Kılavuzunu okuyordum ve herhangi bir rastgele dizgiyi camelCase notasyonuna dönüştürmek için algoritmalarına rastladım. Bu zorlu mücadelede, süper rekabetçi Java gönderilerinizi kod-golf zorluklarına yazarken kafanızdaki tüm bu şeyleri yapmak istemediğiniz için bu algoritmayı uygulamanız gerekir.

Not: Algoritmada bazı küçük değişiklikler yaptım. Aşağıda belirtilen olanı kullanmanız gerekir.

Algoritması

İsteğe bağlı bir giriş dizesiyle başlar ve aşağıdaki işlemleri ona uygularsınız:

  1. Tüm kesme işaretlerini kaldır `'
  2. Sonucu bölerek kelimelere ayırın
    • alfasayısal olmayan ve bir rakam olmayan karakterler [^a-zA-Z0-9]
    • Her iki tarafta küçük harflerle çevrili büyük harfler. abcDefGhI jkörneğin verimlerabc Def Ghi jk
  3. Her kelimeyi küçük harf.
  4. Her kelimenin ilk karakteri değil, ilk kelimenin büyük harfleri.
  5. Tüm kelimeleri tekrar bir araya getirin.

Ek Notlar

  • Giriş yalnızca yazdırılabilir ASCII içerecektir.
  • Bir rakam, bir kelimenin ilk harfiyse, olduğu gibi bırakın ve bu kelimede başka bir şey belirtmeyin.
  • Giriş her zaman en az bir karaktere sahip olacaktır.

kurallar

Test durumları

"Programlama Bulmacaları ve Kod Golf" -> "programlamaPuzzlesCodeGolf"
"XML HTTP isteği" -> "xmlHttpRequest"
"iOS'ta IPv6'yı destekliyor mu?" -> "destekIpv6OnIos"
"W1th bazı Somehing, apo'strophe ve 'punc] tuation" -> "someThingW1thApostrophesAndPuncTuation"
"özel bir şey yok" -> "hiçbir şey özel"
"5 özel ca5e" -> "5 özel Ca5e"
"1337" -> "1337"
"1337-spEAk" -> "1337Speak"
"whatA karışıklık" -> "whataMess"
"abcD" -> "abcd"
"a" -> "a"
"B" -> "b"

Mutlu Kodlama!


3
İlginç, buna "camelCase" dendiğini bilmiyordum. Adı uygun sanırım ...
Ashwin Gupta

4
Daha fazlası: snake_case&PascalCase
Martijn

14
Tabii snake_caseki Python yüzünden @Martijn . FORTH da var FORTHCASEve APL varunreadable in any case
kedi

Test durumu 4 ApostropheSçıktıda olmalıdır .
Titus,

@Titus Hayır, doğru. Kesme işareti giriş bölünmeden önce kaldırılır.
Denker

Yanıtlar:


13

Retina , 56 bayt

Bayt sayısı, ISO 8859-1 kodlamasını varsayar.

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

Çevrimiçi deneyin!

açıklama

Bu, tam anlamıyla şartname uygular:

T`'\`

Kesme tahtalarını ve arka tırnakları çıkarın.

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

Dizgiyi sözcük olmayan karakterlerin etrafına bölün (bu ifadede regex de rakamları ve alt çizgi hariç tutar) veya solda küçük harf, altda büyük harf, küçük harf sağ veya altta olan konumlar. Bu, iki harfli olmayan, üst üste rakamsız karakterler veya dize başında daha önemli olan bazı boş segmentler oluşturur. _Seçeneği olanlardan kurtuluruz . Burada, "bölmek", kalan her bir parçayı kendi çizgisine koymak anlamına gelir.

T`L`l

Her şeyi küçük harfe dönüştürün.

T`l`L`¶.

Satır beslemeden sonra gelen her karakteri büyük harfe dönüştürün. Bu, ilk kelimeyi atlayacak, çünkü önünde hiç besleme yok.

Her şeyi bir araya getirmek için bordürlerden kurtulun.


Beni yendin. Güzel bir!
mbomb007

Bu soru biraz garip olabilir, fakat ... sizinkinden daha kısa ve aynı zamanda Retina'da da cevabımı göndermeli miyim? Cevabınız görünmeden önce üzerinde çalışıyordum, ama sonra oldu ve şimdi göndermeli miyim diye bilmiyorum.
daavko

5
@daavko Tabii, gönder (genellikle yaklaşımın mevcut cevaba ne kadar farklı olduğuna bağlı olarak karar veririm ... eğer bir yerde traş olmuş bir baytla aynı şey varsa, normalde bu cevabı yorumluyorum, ancak çok daha kısa ise farklı bir yaklaşım, o zaman sadece ayrı bir cevap gönderirdim).
Martin Ender

2
@daavko Bir bakışta olsa gerekli. Cevabınız, Thingolması gereken şekilde büyük harf kullanmayacaktır .
Martin Ender

1
@ MartinBüttner Ah ... Bunu farketmedim. Oh, o zaman başka bir zorluğa başarıyla cevap vereceğim.
daavko

11

Java, 198 190 bayt

+3 bayt çünkü bunu unuttum \W+== [^a-zA-Z0-9_]+ve eşleşmem gerekiyor[^a-zA-Z0-9]+

-200 bayt, user20093 sayesinde - ?:yerine if/else

Çünkü, 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;}

Bu bir lambda. Öyle arayın:

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"));

Okunabilir sürüm:

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;
}

1
Swift değil ...
CalculatorFeline

2
Programlama Bulmacaları ve Kod Golf'üne Hoşgeldiniz! Bu güzel bir ilk cevap!
Alex A.

1
@CatsAreFluffy Ne?
kedi,

koşullu ifadeyi (eğer / else) koşullu ifadeyle (? :) değiştirirseniz, yaklaşık 9 bayt kaydedebilirsiniz
user902383

@ User902383 - -11 bayt için eklediğimi nasıl özledim bilmiyorum. Ne yazık ki _, belirteç sınırlayıcı olarak eşleşmek için 3 eklemek zorunda kaldım .
CAD97

10

JavaScript (ES6), 156 154 152 148 145 145 141 140 bayt

Thanks @Neil (6 bayt), @ETHproductions (3 bayt) ve @ edc65 (7 bayt)

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

Kesme çizgilerini kaldırır, daha sonra özel karakterlere ayırma yerine / çevrili büyük harflerden önce bir değiştirme yapar, ardından uygun kasa ile birleştirir. Ne yazık ki, toLowerCase()ve toUpperCase()rahatsız edici uzun ve zor burada önlemek için vardır ...


1
b.slice(i>0)Yaklaşımınızın sudan döküldüğü farklı bir yaklaşım üzerinde çalışıyordum , ancak bu arada benim eşleşme rejimim, /[A-Z]?([a-z0-9]|[0-9A-Z]{2,})+([A-Z](?![a-z]))?/gzekice zekice replaceyaklaşımınıza 2 bayt kazandırıyor gibi görünüyor .
Neil

1
Veya replacedoğrudan 2 bayttan tasarruf edebilirim :replace(/[a-z](?=[A-Z][a-z])/g,'$& ')
Neil

1
Genellikle match...mapreplace
saatinde

1
@ edc65 Bu yaklaşımla minimum 160 bayt 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())
alıyorum

2
Öte yandan, b=>a+=(a?b[0].toUpperCase():'')+b.slice(!!a).toLowerCase()size bir tane daha 4 bayt kazandırdığına inanıyorum.
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 Perl daha kısa ?! Bu delilik nedir?

: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

İşe yaramaz bir tuşa basmayı farkettiği için Neil'e teşekkürler !


Geçen neden görebilirsiniz :sbir vardır %ama neden ilk iki tutarsızlık?
Neil

@Neil Bah, kas hafızası. Teşekkürler!
Doorknob

5
Perl'den daha az okunabilir olmayı
cat

Bunu tamamen .vimrc
moopet

1
@fruglemonkey 1. :%j<cr>eşdeğer ve daha kısa. 2. Bu, çizgiler arasına boşluk ekler.
Doorknob

5

Mathematica 10.1, 101 bayt

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

ToCamelCaseBenzer şekilde çalışan Capitalizeancak diğer karakterleri küçük harfe ayarlayan belgesiz kullanır .


10.3.0'da değil ..
Simmons

ToCamelCase[n_,m_]:=n<>Capitalize/@mdoğru? Öyle görünüyor. Ve neden kullanmak Prependne zaman #~ToCamelCase~{##2}işler?
Hesap MakinesiFeline

@CatsAreFluffy Bu bana verirToCamelCase::argx: ToCamelCase called with 2 arguments; 1 argument is expected.
LegionMammal978

Peki CamelCase nasıl çalışır? Sadece ToCamelCase[n_]:=""<>Capitalize/@n?
CalculatorFeline

@CatsAreFluffy, bkz bu .
LegionMammal978,

5

Julia, 98 89 bayt

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

Bu bir dizgeyi kabul eden ve bir dize döndüren isimsiz bir işlevdir. Aramak için değişkene atayın.

Burada yaklaşım kapı tokmağı en aynıdır Perl cevabı : replaceboş dize ile kesme ve ters tırnakların splitgerekli durumlarda eşleşen bir düzenli ifadeye bir diziye, dizinin üstünde işlevi her öğe, ilk harfini büyük harfe dizi geri bir dizgeye ve ilk karakteri küçük harfe dönüştürme sonucu.mapucfirstjoinlcfirst


Julia'yı her zaman daha işlevsel, daha ilginç bir Python olarak sevdim ama endsözdiziminden nefret ediyorum . Belki de her şey için sadece adsız işlevler kullanacağım, sonra asla yazmak zorunda kalmayacağım end: D
cat

4

Perl 67 + 1 = 68 bayt

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

-pBayrağı gerektirir ve -lçoklu hat için:

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

Nasıl çalışır:

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.

2

Perl, 87 80 78 bayt

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

-pBayrak için bayt eklendi .

Öncelikle, girişteki tüm karakterleri silmek için y///harf çevirisi operatörünü kullanırız :d'`

y/'`//d;

Sonra kodun et geliyor:

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

(giriş sırasını $_uygun konumlara böldükten \Ksonra, eşleşmeden önceki kısmı gerçek eşleşmeden çıkarmak için eşleştirme dizesindeki fantaziyi kullanarak )

          map{ucfirst lc}

(dizenin her bölünmüş kısmı üzerinde eşleyin ve dizenin tamamını küçük harf yapın, sonra değiştirilen dizenin ilk karakterini büyük harf yapın)

$_=join'',

(Boş dizgiye katılın $_ve sonunda basılan sihirli alt çizgiye tekrar atayın )

Son olarak, ilk mektubu regex ile eşleştirerek ve \lyerine yerleştirilen dizgede kullanarak , önceki yönteme göre 2 bayt tasarruf sağlayarak küçük harf :

lcfirst

Sayesinde @ MartinBüttner 7 byte için ( [^a-zA-Z\d]-> \W|_)!


1
Bunu kıskanıyorum \K...;)
Martin Ender

2

Lua, 127 Bayt

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

Stdin'den bir dize kabul eder ve deve sonuçları döndürür.

Muhtemelen hala daha iyi bir çözüm arayacak, çünkü her şeyi bir değişkende saklamak yetersiz kalıyor.

Ama her neyse, genel olarak oldukça basit:

 z:gmatch('%w+')

Bu beni biraz bayt kazandıran güzelliktir. gmatch, diziye göre %w+yalnızca alfasayısalları kapmak için dizgiyi böler .

Bundan sonra basit dize işlemleri. string.upper, string.lower ve bitti.


2

PHP, 145 122 133 bayt

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

Dosyaya kaydet, CLI'den ara.
Tek bir komut satırı argümanından girdi alır; Gerektiğinde kaçış tırnak ve boşluk.

Yıkmak

<?=                 // 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
    ))))
));

lcfirst23 byte tasarruf sağlayarak, bunu tek bir komuta indirgeyebilirim
Kesme işareti düzeltmek ek değiştirme durumda için 11 bayt mal.


1

Kotlin , 160 Bayt

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

Amacım diğer "alternatif Java" Scala olmaktı, bu yüzden sonuçlarımdan biraz memnunum. Regex'i Java'dan çaldım cevabından .

Şununla test et:

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)) }

}

Bu noktada herkesin optimize edilmiş regex'i "ödünç aldığını" \W|_|(?<=[a-z])(?=[A-Z][a-z])veya örneğin onu değiştirdiğini düşünüyorum. [\W_]+
CAD

Eğer harita ve uzatma fonksiyonu üzerine bazı kaydedebilirsinizfun String.a()=replace(Regex("['`]"),"").split(Regex("[\\W_]+|(?<=[a-z])(?=[A-Z][a-z])")).joinToString(""){it.toLowerCase().capitalize()}.decapitalize()
bir olası

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}

Tester:

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"))

Dikmeler CAD97 ve özür Nathan Merrill :)


1
Sen değiştirerek 6 bayt kaydedebilirsiniz [^a-zA-Z0-9]+ile [\\W_]+.
CAD

0

C 272 karakter

C programı argüman 1 olarak tırnak içinde camelCase dizesini iletir. Bu problem açıklamasında çok var

#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);}

Sen gerek #include<string.h>için strlen, strtokve toupper, ve #include<ctype.h>için isalnum.
Mego

Cygwin'de gcc 3.4.4 kullanarak buna ihtiyacım yoktu. Extern int varsayılarak, otomatik olarak bağlanmaları gerekir.
cleblanc

İle ./camel "Programming Puzzles & Code Golf"cygwin (gcc 3.4.4 ile derlenmiş), benim hemen programmingPuzzlesCodeEGolf. 5.3.0 ile aynı çıktı.
Mego

Bok. ben de. Golf yaparken bir böcek yaratmış olmalıyım. Şu an bakıyorum ...
cleblanc

Sorun şu ki golf oynadıktan sonra diğer tokenizer dizelerini ekledim ve yeterince test etmedim. '&' İşaretini strtok çağrısından kaldırırsanız, bu giriş üzerinde çalışır.
cleblanc

0

JavaScript, 123 bayt

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

Okunabilir sürüm

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

Kesme işaretini kaldırın, ilk karakterin küçük harf, son karakterin küçük harf ve birden çok büyük harflerden oluşan herhangi bir gruplandırmasını, büyük harfle değiştirilen son karakterin yerine, 1 veya daha fazla alfasayısal olmayan karakter + 1 karakterden oluşan herhangi bir grupla eşleştirin.

[r = "Değiştir"] Mrw247'nin çözümünden bir numara.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.