Chuyển đổi sang camelCase


34

Các thách thức

Tôi đã đọc Hướng dẫn về Phong cách Java của Google vào một ngày khác và tình cờ tìm thấy thuật toán của họ để chuyển đổi bất kỳ chuỗi tùy ý nào thành ký hiệu camelCase. Trong thử thách này, bạn phải thực hiện thuật toán này vì bạn không muốn thực hiện tất cả những thứ này trong đầu khi bạn đang viết các bài nộp Java siêu cạnh tranh của mình cho các thử thách chơi gôn.

Lưu ý: Tôi đã thực hiện một số điều chỉnh nhỏ cho thuật toán. Bạn cần sử dụng một trong những chỉ định dưới đây.

Thuật toán

Bạn bắt đầu với một chuỗi đầu vào tùy ý và áp dụng các thao tác sau cho chuỗi đó:

  1. Xóa tất cả các dấu nháy đơn `'
  2. Chia kết quả thành các từ bằng cách chia tại
    • các ký tự không phải là chữ số và không phải là một chữ số [^a-zA-Z0-9]
    • Các chữ cái in hoa được bao quanh bởi các chữ cái viết thường ở cả hai bên. abcDefGhI jkví dụ sản lượngabc Def Ghi jk
  3. Chữ thường mỗi chữ.
  4. Viết hoa ký tự đầu tiên của mọi từ trừ từ đầu tiên.
  5. Tham gia tất cả các từ trở lại với nhau.

Ghi chú bổ sung

  • Đầu vào sẽ chỉ chứa ASCII có thể in được.
  • Nếu một chữ số là chữ cái đầu tiên trong một từ, hãy để nguyên như vậy và đừng viết hoa một từ khác trong từ này.
  • Đầu vào sẽ luôn có ít nhất một ký tự.

Quy tắc

Các trường hợp thử nghiệm

"Câu đố lập trình & Golf Code" -> "lập trìnhPu phunCodeGolf"
"Yêu cầu HTTP XML" -> "xmlHttpRequest"
"hỗ trợ IPv6 trên iOS?" -> "hỗ trợIpv6OnIos"
"Một số bài hát w1th, apo'strophe's và 'punc]" -> "someT BreathW1thApostrophesAndPuncTinating"
"không có gì đặc biệt" -> "không có gì đặc biệt"
"5pecial ca5e" -> "5pecialCa5e"
"1337" -> "1337"
"1337-spEAk" -> "1337Speak"
"whatA mess" -> "whataMess"
"abcD" -> "abcd"
"a" -> "a"
"B" -> "b"

Chúc mừng mã hóa!


3
Thật thú vị, tôi không bao giờ biết điều này được gọi là "camelCase". Tên phù hợp Tôi cho rằng ...
Ashwin Gupta

4
Có nhiều hơn: snake_case&PascalCase
Martijn

14
@Martijn snake_casevì Python, tất nhiên. FORTH cũng có FORTHCASEvà APL cóunreadable in any case
mèo

Trường hợp thử nghiệm 4 nên có ApostropheStrong đầu ra.
Tít

@Titus Không, đúng rồi. Dấu nháy đơn được loại bỏ trước khi đầu vào được tách.
Denker

Câu trả lời:


13

Võng mạc , 56 byte

Số lượng byte giả định mã hóa ISO 8859-1.

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

Hãy thử trực tuyến!

Giải trình

Điều này thực hiện các đặc điểm kỹ thuật hoàn toàn theo nghĩa đen:

T`'\`

Loại bỏ dấu nháy đơn và backticks.

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

Tách chuỗi xung quanh các ký tự không phải từ (trong regex, điều này cũng loại trừ các chữ số và dấu gạch dưới), hoặc gạch dưới hoặc các vị trí có chữ thường ở bên trái và chữ hoa, chữ thường ở bên phải. Điều này sẽ tạo ra một số phân đoạn trống khi có hai ký tự không chữ, không chữ số trong một hàng hoặc quan trọng hơn ở đầu chuỗi. Chúng tôi thoát khỏi những người có _tùy chọn. Ở đây, "tách" có nghĩa là đặt từng phần còn lại trên dòng riêng của nó.

T`L`l

Chuyển đổi mọi thứ thành chữ thường.

T`l`L`¶.

Chuyển đổi từng ký tự xảy ra sau dòng cấp dữ liệu thành chữ hoa. Điều này sẽ thuận tiện bỏ qua từ đầu tiên vì không có linefeed ở phía trước của nó.

Loại bỏ các nguồn cấp dữ liệu để tham gia mọi thứ lại với nhau.


Bạn đánh bại tôi vào nó. Đẹp quá
mbomb007

Câu hỏi này có thể hơi lạ, nhưng ... tôi có nên đăng câu trả lời của mình nếu nó ngắn hơn của bạn và cả ở Retina không? Tôi đã làm việc với nó trước khi câu trả lời của bạn xuất hiện, nhưng sau đó nó đã làm và bây giờ tôi không biết liệu tôi có nên đăng nó không.
daavko

5
@daavko Chắc chắn, hãy đăng nó (Tôi thường quyết định dựa trên cách tiếp cận khác nhau với câu trả lời hiện có ... nếu đó là điều tương tự với một byte bị xóa ở đâu đó tôi thường chỉ nhận xét về câu trả lời đó, nhưng nếu nó ngắn hơn rất nhiều về một cách tiếp cận khác, sau đó tôi chỉ cần đăng một câu trả lời riêng).
Martin Ender

2
@daavko Việc xem xét là cần thiết mặc dù. Lưu ý rằng câu trả lời của bạn không giữ lại chữ viết hoa Thingmặc dù vậy.
Martin Ender

1
@ MartinBüttner Oh ... Tôi không nhận thấy điều đó. Oh, tôi sẽ trả lời thành công một số thách thức khác.
daavko

11

Java, 198 190 byte

+3 byte vì tôi quên rằng \W+== [^a-zA-Z0-9_]+và tôi cần khớp[^a-zA-Z0-9]+

-11 byte nhờ user20093 - ?:thay vì if/else

Bởi vì, 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;}

Đây là một lambda. Gọi như vậy:

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

Phiên bản dễ đọc:

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
Đó không phải là Swift ...
CalculatorFeline

2
Chào mừng bạn đến với Câu đố lập trình & Code Golf! Đây là một câu trả lời đầu tiên tốt đẹp!
Alex A.

1
@CatsAreFluffy Gì?
mèo

nếu bạn thay thế câu lệnh có điều kiện (if /
other

Không biết làm thế nào tôi đã bỏ lỡ @ user902383 - được thêm cho -11 byte. Thật không may, tôi đã phải thêm 3 để khớp _với dấu phân cách mã thông báo.
CAD97

10

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

Cảm ơn @Neil (6 byte), @ETHproductions (3 byte) và @ 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

Loại bỏ các dấu nháy đơn, sau đó thực hiện thay thế để phân chia các ký tự đặc biệt / trước các chữ viết hoa được bao quanh, sau đó kết hợp với các vỏ bọc thích hợp. Thật không may, toLowerCase()toUpperCase()thật khó chịu lâu và khó tránh ở đây ...


1
Tôi đã làm việc theo một cách tiếp cận khác mà cách tiếp cận của bạn b.slice(i>0)thổi ra khỏi nước, nhưng trong thời gian đó, biểu thức phù hợp của /[A-Z]?([a-z0-9]|[0-9A-Z]{2,})+([A-Z](?![a-z]))?/gtôi xuất hiện để tiết kiệm 2 byte so với cách replacetiếp cận khéo léo khác của bạn .
Neil

1
Hoặc tôi chỉ có thể lưu replacetrực tiếp 2 byte của bạn :replace(/[a-z](?=[A-Z][a-z])/g,'$& ')
Neil

1
Thường match...mapcó thể được thay thế bằngreplace
edc65

1
@ edc65 Tôi nhận được tối thiểu 160 byte với cách tiếp cận đó: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
Mặt khác, tôi muốn cung cấp b=>a+=(a?b[0].toUpperCase():'')+b.slice(!!a).toLowerCase()mà tôi tin rằng sẽ giúp bạn tiết kiệm thêm 4 byte.
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 ngắn hơn Perl?! Sự điên rồ này là gì?

: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

Cảm ơn Neil vì đã phát hiện ra một tổ hợp phím vô dụng!


Tôi có thể thấy tại sao cuối cùng :scó một %nhưng tại sao sự không nhất quán trong hai đầu tiên?
Neil

@Neil Bah, bộ nhớ cơ. Cảm ơn!
Doorknob

5
Quản lý để dễ đọc hơn Perl, quá +1
mèo

Tôi hoàn toàn thêm phần này vào .vimrc của tôi
moopet

1
@fruglemonkey 1. :%j<cr>tương đương và ngắn hơn. 2. Điều đó thêm khoảng trắng giữa các dòng.
Doorknob

5

Toán học 10.1, 101 byte

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

Sử dụng không có giấy tờ ToCamelCase, hoạt động tương tự Capitalizenhưng đặt các ký tự khác thành chữ thường.


Không phải trong 10.3.0 ..
Một Simmons ngày

ToCamelCase[n_,m_]:=n<>Capitalize/@mđúng không? Có vẻ như nó. Và tại sao sử dụng Prependkhi #~ToCamelCase~{##2}làm việc?
Máy

@CatsAreFluffy Điều đó mang lại cho tôiToCamelCase::argx: ToCamelCase called with 2 arguments; 1 argument is expected.
LegionMammal978

Chà, CamelCase hoạt động như thế nào? Chỉ là ToCamelCase[n_]:=""<>Capitalize/@n?
Máy

@CatsAreFluffy, xem cái này .
LegionMammal978

5

Julia, 98 89 byte

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

Đây là một hàm ẩn danh chấp nhận một chuỗi và trả về một chuỗi. Để gọi nó, gán nó cho một biến.

Cách tiếp cận ở đây là giống như trong tay nắm cửa của Perl câu trả lời : replacedấu nháy và backticks với chuỗi rỗng, splitvào một mảng trên một biểu thức chính quy phù hợp với các trường hợp cần thiết, mapcác ucfirstchức năng trên mảng chữ hoa chữ cái đầu tiên của mỗi phần tử, joinmảng trở lại thành một chuỗi và lcfirstkết quả để chuyển đổi ký tự đầu tiên thành chữ thường.


Tôi luôn thích Julia là một Python có chức năng hơn, thú vị hơn nhưng tôi ghét endcú pháp. Có lẽ tôi sẽ chỉ sử dụng các hàm ẩn danh cho mọi thứ, sau đó tôi không bao giờ phải gõ 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

Yêu cầu -pcờ và -lcho nhiều dòng:

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

Làm thế nào nó hoạt động:

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 byte

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

Byte thêm cho -pcờ.

Đầu tiên, chúng tôi sử dụng y///toán tử chuyển ngữ để xóa dtất cả các '`ký tự trong đầu vào:

y/'`//d;

Sau đó đến thịt của mã:

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

(tách chuỗi đầu vào $_ở các vị trí thích hợp, sử dụng chuỗi ưa thích \Ktrong chuỗi khớp để loại trừ phần trước chuỗi đó khỏi khớp thực tế)

          map{ucfirst lc}

(ánh xạ qua từng phần tách của chuỗi và tạo toàn bộ chữ thường, sau đó tạo ký tự đầu tiên của chữ hoa chuỗi đã sửa đổi)

$_=join'',

(tham gia vào chuỗi trống và gán lại cho dấu gạch dưới ma thuật $_, được in ở cuối)

Cuối cùng, chúng tôi viết thường chữ cái đầu tiên bằng cách khớp với regex và sử dụng \lchuỗi thay thế bằng hàm dựng sẵn, tiết kiệm 2 byte so với phương thức trước:

lcfirst

Cảm ơn @ MartinBüttner cho 7 byte ( [^a-zA-Z\d]-> \W|_)!


1
Làm thế nào tôi ghen tị với điều đó \K...;)
Martin Ender

2

Lua, 127 byte

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

Chấp nhận một chuỗi từ stdin và trả về kết quả camelized.

Có lẽ vẫn sẽ tìm kiếm một giải pháp tốt hơn vì lưu trữ mọi thứ trong một biến cảm thấy không hiệu quả.

Nhưng dù sao, nói chung khá đơn giản:

 z:gmatch('%w+')

Đây là vẻ đẹp đã tiết kiệm cho tôi một chút byte. gmatch sẽ phân chia chuỗi dựa trên mẫu: %w+chỉ lấy các chữ số.

Sau đó, nó hoạt động chuỗi đơn giản. string.upper, string.lower và thực hiện.


2

PHP, 145 122 133 byte

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

Lưu vào tập tin, gọi từ CLI.
Lấy đầu vào từ một đối số dòng lệnh; báo giá thoát và khoảng trắng khi cần thiết.

phá vỡ

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

lcfirstđược phép giảm điều này thành một lệnh duy nhất, tiết kiệm 23 byte.
Sửa các dấu nháy tốn 11 byte cho trường hợp thay thế bổ sung.


1

Kotlin , 160 byte

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

Mục tiêu của tôi là Scala, "Java thay thế" khác, vì vậy tôi phần nào hài lòng với kết quả của mình. Tôi đã đánh cắp regex từ câu trả lời Java .

Kiểm tra nó với:

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

}

Tại thời điểm này, tôi nghĩ rằng tất cả mọi người đang "mượn" regex được tối ưu hóa \W|_|(?<=[a-z])(?=[A-Z][a-z])hoặc sửa đổi một chút, ví dụ như. [\W_]+
CAD97

bạn có thể tiết kiệm một số trên bản đồ và chức năng mở rộngfun 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}

Người kiểm tra:

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

Đạo cụ cho CAD97 và lời xin lỗi tới Nathan Merrill :)


1
Bạn có thể lưu 6 byte bằng cách thay thế [^a-zA-Z0-9]+bằng [\\W_]+.
CAD97

0

C 272 ký tự

Chương trình C chuyển chuỗi sang camelCase trong ngoặc kép làm đối số 1. Có rất nhiều vấn đề về vấn đề này ...

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

Bạn cần phải #include<string.h>cho strlen, strtoktoupper, và #include<ctype.h>cho isalnum.
Mego

Tôi không cần nó bằng gcc 3.4.4 trong cygwin. Chúng phải được tự động liên kết trong, giả sử extern int.
cleblanc

Với ./camel "Programming Puzzles & Code Golf"trên cygwin (được biên dịch với gcc 3.4.4), tôi nhận được programmingPuzzlesCodeEGolf. Cùng một đầu ra với 5.3.0.
Mego

Tào lao tôi cũng vậy. Tôi phải tạo ra một lỗi trong khi chơi golf. Tôi đang nhìn vào nó bây giờ ...
cleblanc

Vấn đề là tôi đã thêm các chuỗi mã thông báo khác sau khi chơi golf và không kiểm tra đủ tốt. Nếu bạn xóa '&' khỏi lệnh gọi strtok, nó sẽ hoạt động trên đầu vào đó.
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())

Phiên bản dễ đọc

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

Xóa các dấu nháy đơn, viết chữ thường đầu tiên, chữ thường cuối cùng và bất kỳ nhóm nhiều ký tự viết hoa nào, khớp với bất kỳ nhóm nào có 1 hoặc nhiều ký tự không chữ và số + 1 ký tự khác, thay thế bằng ký tự cuối cùng được viết hoa.

[r = "thay thế"] mẹo từ giải pháp của Mrw247.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.