Перетворити на camelCase


34

Змагання

Днями я читав посібник зі стилів Java Google і наткнувся на їх алгоритм, щоб перетворити будь-яку довільну рядок у нотацію camelCase. У цьому виклику вам належить реалізувати цей алгоритм, оскільки ви не хочете робити все це в голові, коли ви пишете свої супер конкурентоспроможні подання Java на завдання з кодом-гольфу.

Примітка: я вніс деякі невеликі корективи в алгоритм. Вам потрібно скористатися вказаним нижче.

Алгоритм

Ви починаєте з довільного рядка введення та застосовуєте до нього такі операції:

  1. Видаліть усі апострофи `'
  2. Розбийте результат на слова, розділивши на
    • символи, які не буквено-цифрові та не цифри [^a-zA-Z0-9]
    • Великі літери, оточені з двох сторін малими літерами. abcDefGhI jkнаприклад врожайністьabc Def Ghi jk
  3. Мале слово кожне слово.
  4. Пропишіть першими символами кожного, крім першого слова.
  5. З’єднайте всі слова разом.

Додаткові нотатки

  • Вхід буде містити тільки друкований ASCII.
  • Якщо цифра - перша літера в слові, залиште її такою, якою вона є, і не використовуйте щось інше в цьому слові.
  • Вхід завжди матиме хоча б один символ.

Правила

Тестові справи

"Головоломки програмування та код гольфу" -> "програмуванняPuzzlesCodeGolf"
"XML запит HTTP" -> "xmlHttpRequest"
"підтримує IPv6 на iOS?" -> "supportsIpv6OnIos"
"SomeThing w1th, apo'strophe та 'punc] tuation" -> "someThingW1thApostrophesAndPuncTuation"
"нічого особливого" -> "нічого особливого"
"5pecial ca5e" -> "5pecialCa5e"
"1337" -> "1337"
"1337-spEAk" -> "1337Speak"
"whatA безлад" -> "whataMess"
"abcD" -> "abcd"
"a" -> "a"
"B" -> "b"

Щасливе кодування!


3
Цікаво, що я ніколи не знав, що це називається "camelCase". Ім'я підходить, я гадаю,
Ешвін Гупта

4
Є ще: snake_case&PascalCase
Martijn

14
@Martijn snake_caseчерез Python, звичайно. У FORTH також є FORTHCASEі APL маєunreadable in any case
кішка

Тестовий випадок 4 повинен мати ApostropheSу висновку.
Тит

@Titus Ні, це правильно. Апострофи видаляються до розбиття вводу.
Денкер

Відповіді:


13

Сітківка , 56 байт

Кількість байтів передбачає кодування ISO 8859-1.

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

Спробуйте в Інтернеті!

Пояснення

Це реалізує специфікацію досить буквально:

T`'\`

Видаліть апострофи та задні посилання.

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

Розділіть рядок навколо символів, що не містять слів (у регулярному вираженні це також виключає цифри та підкреслення) або підкреслення або позиції, що мають ліворуч і верхній регістр, нижній регістр справа. Це створило б порожні сегменти, коли на початку рядка є два нецифрові, нецифрові символи чи більш важливі. Ми позбавляємось тих, хто має _можливість. Тут «розщеплення» означає поставити кожну частину, що залишилася, на свій власний рядок.

T`L`l

Перетворіть все в малі регістри.

T`l`L`¶.

Перетворіть кожен символ, що виникає після передачі рядка, у верхній регістр. Це зручно пропустити перше слово, оскільки перед ним немає подачі ліній.

Позбавтеся від ліній-стрічок, щоб приєднати все разом.


Ти побив мене до цього. Хороший!
mbomb007

Це запитання може бути трохи дивним, але ... чи варто я розмістити свою відповідь, якщо вона коротша, ніж у вас, а також у сітківці? Я працював над цим до того, як з’явилася ваша відповідь, але потім це сталося, і тепер я не знаю, чи варто її розміщувати.
daavko

5
@daavko Звичайно, опублікуй це (я зазвичай вирішую, виходячи з того, наскільки різний підхід до існуючої відповіді ... якщо це точно та сама річ з байтом, який десь поголений, я зазвичай просто коментую цю відповідь, але якщо це набагато коротше іншого підходу, тоді я просто опублікую окрему відповідь).
Мартін Ендер

2
@daavko Шукати потрібно, хоча. Зауважте, що ваша відповідь не зберігає великої літери, Thingхоча і повинна.
Мартін Ендер

1
@ MartinBüttner О, я цього не помічав. Ну добре, тоді я успішно відповім на якийсь інший виклик.
daavko

11

Ява, 198 190 байт

+3 байт, тому що я забув це \W+== [^a-zA-Z0-9_]+і мені потрібно відповідати[^a-zA-Z0-9]+

-11 байт завдяки користувачу20093 - ?:замість if/else

Тому що, 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;}

Це лямбда. Телефонуйте так:

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

Читаема версія:

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
Це не Швидкий ...
CalculatorFeline

2
Ласкаво просимо до головоломки програмування та коду для гольфу! Це хороша перша відповідь!
Алекс А.

1
@CatsAreFluffy Що?
кіт

якщо ви заміните умовний вислів (якщо / інше) на умовний вираз (? :), ви можете зберегти близько 9 байт
user902383

Не знаю, як я пропустив це @ user902383 - додано для -11 байт. На жаль, мені довелося додати 3, щоб відповідати _як маркер-роздільник.
CAD97

10

JavaScript (ES6), 156 154 152 148 145 141 140 байт

Дякуємо @Neil (6 байт), @ETHproductions (3 байти) та @ edc65 (7 байт)

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

Видаляє апострофи, потім робить заміну, щоб розділити на спеціальних символів / перед оточеними столицями, а потім поєднати з правильним корпусом. На жаль, toLowerCase()і toUpperCase()тут прикро довго і важко уникнути ...


1
Я працював над іншим підходом, який ваш b.slice(i>0)підхід вибухає з води, але тим часом мій регекс збігу /[A-Z]?([a-z0-9]|[0-9A-Z]{2,})+([A-Z](?![a-z]))?/gдійсно врятує 2 байти за ваш інакше геніальний replaceпідхід.
Ніл

1
Або я міг би просто зберегти 2 байти на вашому replaceбезпосередньо:replace(/[a-z](?=[A-Z][a-z])/g,'$& ')
Ніл

1
Зазвичай match...mapйого можна замінити наreplace
edc65

1
@ edc65 При такому підході я отримую мінімум 160 байт: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
З іншого боку, я хотів би запропонувати, b=>a+=(a?b[0].toUpperCase():'')+b.slice(!!a).toLowerCase()що, на мою думку, заощаджує вам ще 4 байти.
Ніл

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 ?! Що це за божевілля?

: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

Дякуємо Нілу за виявлення марного натискання клавіш!


Я бачу, чому останній :sмає, %але чому непослідовність у перших двох?
Ніл

@Neil Bah, м'язова пам’ять. Спасибі!
Дверна ручка

5
Вдається бути менш читабельним, ніж Perl, теж +1
кіт

Я повністю додаю це до свого .vimrc
moopet

1
@fruglemonkey 1. :%j<cr>еквівалентний і коротший. 2. Що додає пробіли між рядками.
Дверна ручка

5

Mathematica 10,1, 101 байт

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

Використовується бездокументований ToCamelCase, який працює аналогічно, Capitalizeале встановлює інші символи в малі регістри.


Не в 10.3.0 ..
А Сіммонс

Є чи ToCamelCase[n_,m_]:=n<>Capitalize/@mправильно? Здається, це так. І навіщо використовувати, Prependколи #~ToCamelCase~{##2}працює?
CalculatorFeline

@CatsAreFluffy Це дає меніToCamelCase::argx: ToCamelCase called with 2 arguments; 1 argument is expected.
LegionMammal978

Ну, як працює CamelCase? Просто ToCamelCase[n_]:=""<>Capitalize/@n?
CalculatorFeline

@CatsAreFluffy, дивіться це .
LegionMammal978

5

Юлія, 98 89 байт

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

Це анонімна функція, яка приймає рядок і повертає рядок. Щоб викликати його, призначте його змінній.

Підхід тут такий же , як в дверну ручку в Perl відповіді : replaceапостроф і зворотні лапки з нового рядка, splitв масив на регулярний вираз , яке відповідає необхідних випадках, функція над масивом великою першу букву кожного елемента масиву назад в рядок, і результат перетворення першого символу в малі регістри.mapucfirstjoinlcfirst


Мені завжди подобалася Юлія як більш функціональний, цікавіший Python, але ненавиджу endсинтаксис. Можливо, я просто буду використовувати анонімні функції для всього, тоді мені ніколи не доведеться набирати end: D
кіт

4

Perl 67 + 1 = 68 байт

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

Потрібен -pпрапор та -lдля рядків:

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

Як це працює:

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 байт

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

Байт додано для -pпрапора.

По-перше, ми використовуємо y///оператор транслітерації, щоб dвибрати всі '`символи вхідних даних:

y/'`//d;

Потім виходить м'ясо коду:

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

(розділіть рядок введення $_на відповідні місця, використовуючи фантазію \Kв рядку відповідності, щоб виключити частину, що передує йому, із фактичної відповідності)

          map{ucfirst lc}

(переведіть на кожну розділену частину рядка та зробіть всю рядку з малої літери, а потім зробіть перший символ верхнього регістру зміненої рядки)

$_=join'',

(приєднайтесь до порожнього рядка та перезазначте магічне підкреслення $_, яке надрукується наприкінці)

Нарешті, ми малі літери першої літери , підрівнюючи її регулярним виразом та використовуючи \lв рядок заміни вбудований, зберігаючи 2 байти за попередній метод:

lcfirst

Дякуємо @ MartinBüttner за 7 байт ( [^a-zA-Z\d]-> \W|_)!


1
Як я заздрю ​​цьому \K...;)
Мартін Ендер

2

Луа, 127 байт

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 та повертає непересічні результати.

Напевно, все-таки шукатимуть кращого рішення, оскільки зберігання всього в змінній буде неефективним.

Але взагалі досить просто:

 z:gmatch('%w+')

Це та краса, яка врятувала мене трохи байтів. gmatch розділить рядок на основі шаблону: %w+який захоплює лише буквено-цифрові.

Після цього це прості струнні операції. string.upper, string.lower і зроблено.


2

PHP, 145 122 133 байт

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

Збережіть у файл, зателефонуйте з CLI.
Приймає дані з аргументу одного командного рядка; уникнути цитат та пробілів, де це необхідно.

зламатися

<?=                 // 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дозволило звести це до однієї команди, заощадивши 23 байти.
Виправлення апострофа коштувало 11 байт для додаткового випадку заміни.


1

Котлін , 160 байт

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

Моєю метою було стати Скалою, іншою "альтернативною Java", тому я дещо задоволений своїми результатами. Я вкрав регулярний вираз із відповіді Java .

Перевірте це за допомогою:

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

}

У цей момент я думаю, що кожен "запозичує" оптимізований регулярний вираз \W|_|(?<=[a-z])(?=[A-Z][a-z])або трохи модифікує його, наприклад. [\W_]+
CAD97

ви можете зберегти їх на карті та функції розширенняfun String.a()=replace(Regex("['`]"),"").split(Regex("[\\W_]+|(?<=[a-z])(?=[A-Z][a-z])")).joinToString(""){it.toLowerCase().capitalize()}.decapitalize()
можливо

1

Скала, 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}

Тестер:

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

Реквізит до CAD97 та вибачення перед Натаном Мерріллом :)


1
Ви можете зберегти 6 байт, замінивши [^a-zA-Z0-9]+на [\\W_]+.
CAD97

0

C 272 символи

Програма C передає рядок camelCase в лапках як аргумент 1. У цій постановці проблеми є безліч готчей ...

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

Вам потрібно #include<string.h>для strlen, strtokі toupper, і #include<ctype.h>для isalnum.
Mego

Мені це не потрібно було, використовуючи gcc 3.4.4 в cygwin. Вони повинні бути автоматично пов'язані між собою, припускаючи зовнішній int.
клеблан

З ./camel "Programming Puzzles & Code Golf"cygwin (складений з gcc 3.4.4), я розумію programmingPuzzlesCodeEGolf. Той самий вихід з 5.3.0.
Mego

Лайно. я також. Я, мабуть, створив помилку під час гольфу. Я зараз на це
дивлюсь

Проблема полягала в тому, що я додав інші струни токенізатора після гольфу і не перевірив його досить добре. Якщо ви вилучите "&" з виклику strtok, він працює на цьому вході.
клеблан

0

JavaScript, 123 байти

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

Читаема версія

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

Вилучіть апострофи, зробіть перший символ нижчим регістром, останній рядковим символом і будь-яке групування кількох великих літер, збігайте будь-яку групу з 1 або декількох не буквено-цифрових знаків + 1 іншого символу, замініть цим останнім символом з великої літери.

[r = "замінити"] трюк з рішення Mrw247.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.