Konversikan ke camelCase

34

Tantangan

Saya sedang membaca Panduan Gaya Java Google beberapa hari yang lalu dan menemukan algoritma mereka untuk mengubah sembarang string menjadi notasi camelCase. Dalam tantangan ini Anda harus menerapkan algoritma ini karena Anda tidak ingin melakukan semua hal ini di kepala Anda ketika Anda menulis kiriman Java Anda yang super kompetitif ke tantangan kode-golf.

Catatan: Saya membuat beberapa penyesuaian kecil pada algoritma. Anda harus menggunakan yang ditentukan di bawah ini.

Algoritma

Anda mulai dengan string input sembarang dan menerapkan operasi berikut untuk itu:

  1. Hapus semua apostrof `'
  2. Bagi hasil menjadi kata-kata dengan membelah
    • karakter yang bukan alfanumerik dan bukan digit [^a-zA-Z0-9]
    • Huruf besar yang dikelilingi oleh huruf kecil di kedua sisi. abcDefGhI jkmisalnya hasil panenabc Def Ghi jk
  3. Huruf kecil setiap kata.
  4. Huruf besar pertama dari setiap kata kecuali kata pertama.
  5. Gabungkan semua kata kembali bersama.

Catatan tambahan

  • Input hanya akan berisi ASCII yang dapat dicetak.
  • Jika digit adalah huruf pertama dalam sebuah kata, biarkan seperti apa adanya dan jangan kapitalisasi sesuatu yang lain dalam kata ini.
  • Input akan selalu memiliki setidaknya satu karakter.

Aturan

  • Fungsi atau program lengkap diizinkan.
  • Aturan default untuk input / output.
  • Celah standar berlaku.
  • Ini adalah , sehingga byte-count terendah akan menang. Tiebreak adalah pengiriman sebelumnya.

Uji kasus

"Programming Puzzles & Code Golf" -> "programmingPuzzlesCodeGolf"
"Permintaan HTTP XML" -> "xmlHttpRequest"
"mendukung IPv6 di iOS?" -> "supportIpv6OnIos"
"SomeThing w1th, apo'strophe's dan 'punc] tuation" -> "someThingW1thApostrophesAndPuncTuation"
"nothing special" -> "nothingSpecial"
"5pecial ca5e" -> "5pecialCa5e"
"1337" -> "1337"
"1337-spEAk" -> "1337Speak"
"whatA mess" -> "whataMess"
"abcD" -> "abcd"
"a" -> "a"
"B" -> "b"

Selamat Coding!

Denker
sumber
3
Menarik, saya tidak pernah tahu ini disebut "camelCase". Namanya pas, saya kira ...
Ashwin Gupta
4
Ada lebih banyak: snake_case&PascalCase
Martijn
14
@ Martijn snake_casekarena Python, tentu saja. FORTH juga memiliki FORTHCASEdan APL memilikiunreadable in any case
kucing
Test case 4 seharusnya ada ApostropheSdi output.
Titus
@Titus Tidak, ini benar. Tanda kutip dihapus sebelum input dibelah.
Denker

Jawaban:

13

Retina , 56 byte

Hitungan byte mengasumsikan penyandian ISO 8859-1.

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

Cobalah online!

Penjelasan

Ini mengimplementasikan spesifikasi secara harfiah:

T`'\`

Hapus tanda kutip dan backticks.

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

Pisahkan string di sekitar karakter non-kata (dalam regex ini juga tidak termasuk angka dan garis bawah), atau garis bawah atau posisi yang memiliki huruf kecil di kiri dan dan huruf besar, huruf kecil di kanan. Ini akan membuat beberapa segmen kosong ketika ada dua karakter non-huruf, non-digit berturut-turut, atau lebih penting di awal string. Kami menyingkirkan mereka yang memiliki _opsi. Di sini, "pemisahan" berarti menempatkan setiap bagian yang tersisa pada barisnya sendiri.

T`L`l

Konversikan semuanya menjadi huruf kecil.

T`l`L`¶.

Konversi setiap karakter yang terjadi setelah linefeed ke huruf besar. Ini dengan mudah akan melewatkan kata pertama karena tidak ada linefeed di depannya.

Singkirkan semua umpan baris untuk menyatukan semuanya kembali.

Martin Ender
sumber
Anda mengalahkan saya untuk itu. Yang bagus!
mbomb007
Pertanyaan ini mungkin agak aneh, tetapi ... haruskah saya memposting jawaban saya jika lebih pendek dari Anda dan juga di Retina? Saya sedang mengerjakannya sebelum jawaban Anda muncul, tetapi kemudian itu terjadi dan sekarang saya tidak tahu apakah saya harus mempostingnya.
daavko
5
@daavko Tentu, posting itu (saya biasanya memutuskan berdasarkan seberapa berbeda pendekatannya dengan jawaban yang ada ... jika itu hal yang sama persis dengan byte yang dicukur di suatu tempat saya biasanya hanya mengomentari jawaban itu, tetapi jika itu jauh lebih pendek dari pendekatan yang berbeda, maka saya baru saja memposting jawaban yang terpisah).
Martin Ender
2
@daavko Pencarian ini diperlukan meskipun. Perhatikan bahwa jawaban Anda tidak mempertahankan kapitalisasi Thingmeskipun seharusnya.
Martin Ender
1
@ MartinBüttner Oh ... Saya tidak memperhatikan itu. Oh well, kalau begitu aku akan berhasil menjawab beberapa tantangan lain.
daavko
11

Java, 198 190 byte

+3 byte karena saya lupa bahwa \W+== [^a-zA-Z0-9_]+dan saya harus mencocokkan[^a-zA-Z0-9]+

-11 byte terima kasih kepada user20093 - ?:bukan if/else

Karena, Jawa.

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

Ini adalah lambda. Sebut seperti ini:

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

Versi yang dapat dibaca:

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
sumber
1
Ini bukan Swift ...
CalculatorFeline
2
Selamat Datang di Programming Puzzles & Code Golf! Ini jawaban pertama yang bagus!
Alex A.
1
@CatsAreFluffy Apa?
kucing
jika Anda mengganti pernyataan kondisional (jika / lain) dengan ekspresi kondisional (? :) Anda bisa menghemat sekitar 9 byte
user902383
Tidak tahu bagaimana saya melewatkan @ user902383 - ditambahkan untuk -11 byte. Sayangnya saya harus menambahkan 3 juga untuk mencocokkan _sebagai pembatas token.
CAD97
10

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

Terima kasih @Neil (6 byte), @ETHproduksi (3 byte), dan @ edc65 (7 byte)

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

Menghapus tanda kutip, kemudian melakukan penggantian untuk membagi pada karakter khusus / sebelum modal dikelilingi, kemudian menggabungkan dengan casing yang tepat. Sayangnya, toLowerCase()dan toUpperCase()sangat panjang dan sulit untuk dihindari di sini ...

Mwr247
sumber
1
Saya sedang mengerjakan suatu pendekatan yang berbeda dimana pendekatan Anda b.slice(i>0)berhembus keluar dari air, tetapi sementara itu regex pertandingan saya /[A-Z]?([a-z0-9]|[0-9A-Z]{2,})+([A-Z](?![a-z]))?/gtampaknya menghemat 2 byte dari replacependekatan Anda yang cerdik .
Neil
1
Atau saya hanya bisa menghemat 2 byte pada Anda replacesecara langsung:replace(/[a-z](?=[A-Z][a-z])/g,'$& ')
Neil
1
Biasanya match...mapdapat diganti denganreplace
edc65
1
@ edc65 Saya mendapatkan minimum 160 byte dengan pendekatan itu: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())
ETHproduksi
2
Di sisi lain, saya ingin menawarkan b=>a+=(a?b[0].toUpperCase():'')+b.slice(!!a).toLowerCase()yang saya percaya menghemat 4 byte lagi.
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 lebih pendek dari Perl ?! Gila apa ini?

: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

Terima kasih kepada Neil karena melihat keystroke yang tidak berguna!

Gagang pintu
sumber
Saya bisa melihat mengapa yang terakhir :smemiliki %tetapi mengapa inkonsistensi dalam dua yang pertama?
Neil
@Neil Bah, memori otot. Terima kasih!
Gagang Pintu
5
Berhasil lebih mudah dibaca daripada Perl, juga +1
cat
Saya benar-benar menambahkan ini ke .vimrc
moopet
1
@ fruglemonkey 1. :%j<cr>sama dan lebih pendek. 2. Itu menambahkan spasi di antara garis.
Gagang pintu
5

Mathematica 10.1, 101 bytes

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

Menggunakan yang tidak berdokumen ToCamelCase, yang berfungsi serupa dengan Capitalizetetapi menyetel karakter lain menjadi huruf kecil.

LegionMammal978
sumber
Tidak di 10.3.0 ..
A Simmons
Apakah ToCamelCase[n_,m_]:=n<>Capitalize/@mbenar Sepertinya begitu. Dan mengapa digunakan Prependsaat #~ToCamelCase~{##2}bekerja?
CalculatorFeline
@CatsAreFluffy Yang memberi sayaToCamelCase::argx: ToCamelCase called with 2 arguments; 1 argument is expected.
LegionMammal978
Nah, bagaimana cara kerja CamelCase? Adil ToCamelCase[n_]:=""<>Capitalize/@n?
CalculatorFeline
@CatsAreFluffy, lihat ini .
LegionMammal978
5

Julia, 98 89 byte

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

Ini adalah fungsi anonim yang menerima string dan mengembalikan string. Untuk menyebutnya, tetapkan ke variabel.

Pendekatan di sini adalah sama seperti di Doorknob ini Perl jawaban : replaceapostrof dan tanda kutip mundur dengan string kosong, splitke dalam sebuah array pada ekspresi reguler yang cocok dengan kasus yang diperlukan, mapyang ucfirstfungsi lebih array ke huruf besar huruf pertama dari setiap elemen, joinarray kembali menjadi string, dan lcfirsthasilnya untuk mengubah karakter pertama menjadi huruf kecil.

Alex A.
sumber
Saya selalu menyukai Julia sebagai Python yang lebih fungsional, lebih menarik tetapi saya benci endsintaksisnya. Mungkin saya hanya akan menggunakan fungsi anonim untuk semuanya, maka saya tidak perlu mengetik end: D
cat
4

Perl 67 + 1 = 68 byte

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

Membutuhkan -pbendera, dan -luntuk multi baris:

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

Bagaimana itu bekerja:

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
sumber
2

Perl, 87 80 78 byte

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

Byte ditambahkan untuk -p bendera.

Pertama, kami menggunakan y///operator transliterasi untuk dmenghapus semua '`karakter dalam input:

y/'`//d;

Kemudian muncul daging kode:

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

(pisahkan string input $_di lokasi yang sesuai, menggunakan fancy \Kdi string pertandingan untuk mengecualikan bagian sebelumnya dari pertandingan yang sebenarnya)

          map{ucfirst lc}

(petakan setiap bagian dari string dan buat seluruh string menjadi huruf kecil, kemudian buat karakter pertama dari string yang diubah menjadi huruf besar)

$_=join'',

(gabung dengan string kosong dan tetapkan kembali ke garis bawah ajaib $_, yang akan dicetak pada bagian akhir)

Akhirnya, kami mengurangi huruf pertama dengan mencocokkan regexnya dan menggunakan \ldalam string pengganti dengan builtin, menghemat 2 byte dari metode sebelumnya:

lcfirst

Terima kasih kepada @ MartinBüttner untuk 7 byte ( [^a-zA-Z\d]-> \W|_)!

Gagang pintu
sumber
1
Betapa saya iri itu \K...;)
Martin Ender
2

Lua, 127 Bytes

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

Menerima string dari stdin dan mengembalikan hasil camelized.

Mungkin masih akan mencari solusi yang lebih baik karena menyimpan segala sesuatu dalam suatu variabel terasa tidak efisien.

Tetapi bagaimanapun juga, cukup sederhana secara umum:

 z:gmatch('%w+')

Ini adalah keindahan yang menyelamatkan saya sedikit byte. gmatch akan membagi string berdasarkan pola: %w+yang hanya mengambil alfanumerik.

Setelah itu operasi string sederhana. string.upper, string.lower dan selesai.

Skyl3r
sumber
2

PHP, 145 122 133 byte

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

Simpan ke file, panggilan dari CLI.
Mengambil input dari argumen baris perintah tunggal; melarikan diri kutipan dan ruang kosong jika perlu.

kerusakan

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

lcfirstdiizinkan untuk mengurangi ini menjadi satu perintah, menghemat 23 byte.
Memperbaiki apostrof biaya 11 byte untuk penggantian kasus tambahan.

Titus
sumber
1

Kotlin , 160 Bytes

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

Tujuan saya adalah menjadi Scala, "alternatif Jawa" yang lain, jadi saya agak senang dengan hasil saya. Saya mencuri regex dari Jawa jawaban .

Uji dengan:

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
sumber
Pada titik ini saya pikir semua orang "meminjam" regex yang dioptimalkan \W|_|(?<=[a-z])(?=[A-Z][a-z])atau sedikit memodifikasi misalnya. [\W_]+
CAD97
Anda dapat menyimpan sebagian di peta dan fungsi ekstensifun String.a()=replace(Regex("['`]"),"").split(Regex("[\\W_]+|(?<=[a-z])(?=[A-Z][a-z])")).joinToString(""){it.toLowerCase().capitalize()}.decapitalize()
poss
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}

Penguji:

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

Props untuk CAD97 dan permintaan maaf untuk Nathan Merrill :)

pudar
sumber
1
Anda dapat menyimpan 6 byte dengan menggantinya [^a-zA-Z0-9]+dengan [\\W_]+.
CAD97
0

C 272 karakter

Program C meneruskan string ke camelCase dalam tanda kutip sebagai argumen 1. Ada banyak tentang gotcha dalam pernyataan masalah ini ...

#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
sumber
Anda perlu #include<string.h>untuk strlen, strtokdan toupper, dan #include<ctype.h>untuk isalnum.
Mego
Saya tidak membutuhkannya menggunakan gcc 3.4.4 di cygwin. Mereka harus terhubung secara otomatis, dengan asumsi int eksternal.
cleblanc
Dengan ./camel "Programming Puzzles & Code Golf"di cygwin (dikompilasi dengan gcc 3.4.4), saya mengerti programmingPuzzlesCodeEGolf. Output yang sama dengan 5.3.0.
Mego
Sampah. saya juga. Saya pasti membuat bug saat bermain golf. Saya sedang melihatnya sekarang ...
cleblanc
Masalahnya adalah saya menambahkan string tokenizer lainnya setelah bermain golf dan tidak mengujinya dengan cukup baik. Jika Anda menghapus '&' dari panggilan strtok, itu berfungsi pada input itu.
cleblanc
0

JavaScript, 123 byte

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

Versi yang mudah dibaca

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

Hapus apostrof, buat huruf kecil karakter pertama, huruf kecil karakter terakhir, dan setiap pengelompokan beberapa huruf besar, cocok dengan grup 1 atau lebih karakter non-alfanumerik + 1 karakter lainnya, ganti dengan huruf terakhir yang ditulis dengan huruf kapital.

[r = "ganti"] trik dari solusi Mrw247.

Grax32
sumber