Як перетворити PascalCase в pascal_case?


Відповіді:


163

Спробуйте це для розміру:

$tests = array(
  'simpleTest' => 'simple_test',
  'easy' => 'easy',
  'HTML' => 'html',
  'simpleXML' => 'simple_xml',
  'PDFLoad' => 'pdf_load',
  'startMIDDLELast' => 'start_middle_last',
  'AString' => 'a_string',
  'Some4Numbers234' => 'some4_numbers234',
  'TEST123String' => 'test123_string',
);

foreach ($tests as $test => $result) {
  $output = from_camel_case($test);
  if ($output === $result) {
    echo "Pass: $test => $result\n";
  } else {
    echo "Fail: $test => $result [$output]\n";
  }
}

function from_camel_case($input) {
  preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
  $ret = $matches[0];
  foreach ($ret as &$match) {
    $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
  }
  return implode('_', $ret);
}

Вихід:

Pass: simpleTest => simple_test
Pass: easy => easy
Pass: HTML => html
Pass: simpleXML => simple_xml
Pass: PDFLoad => pdf_load
Pass: startMIDDLELast => start_middle_last
Pass: AString => a_string
Pass: Some4Numbers234 => some4_numbers234
Pass: TEST123String => test123_string

Тут реалізуються такі правила:

  1. Послідовність, що починається з малої літери, повинна супроводжуватися малими літерами та цифрами;
  2. Послідовність, що починається з великої літери, може супроводжуватися будь-яким:
    • одна або кілька великих літер і цифр (з наступним кінцем рядка або великою літерою з наступною малою літерою або цифрою, тобто початком наступної послідовності); або
    • одна або кілька малих літер або цифр.

9
Він працює для рядків CamelCased (як запитав openfrog), але якщо ви використовуєте його з рядком введення, наприклад "r_id" (вже "підкреслено"), він обрізає префікс ("r_"). Гарне рішення, але, безумовно, не універсальне.
Мартін

1
Цікаво, чому ви перевіряєте, чи збігається рядок з рядком all-caps? Яка перевага перетворення лише першого символу на малі (на відміну від усіх символів)?
Джош

1
Більш коротке рішення , яке також може обробляти всі ці випадки використання: stackoverflow.com/a/35719689/4328383
Syone

156

Коротше рішення: Подібно до редактору зі спрощеним регулярним виразом та виправленням проблеми "підкреслення-підкреслення":

$output = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));

PHP Демо | Демонстрація Regex


Зауважте, що подібні випадки SimpleXMLбудуть перетворені на simple_x_m_lвикористання вищезазначеного рішення. Це також можна вважати неправильним використанням позначення справи верблюда (правильним було б SimpleXml), а не помилкою алгоритму, оскільки такі випадки завжди неоднозначні - навіть якщо групувати великі символи в одну рядок ( simple_xml) такий алгоритм завжди вийде з ладу в інших крайових випадках наприклад, XMLHTMLConverterоднолітерні слова біля абревіатур тощо. Якщо ви не заперечуєте проти (досить рідкісних) крайових справ і хочете SimpleXMLправильно попрацювати, ви можете скористатися трохи складнішим рішенням:

$output = ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');

PHP Демо | Демонстрація Regex


Не соромтесь коментувати відповідь клетуса, в якому детально описували тестові випадки, які ви виправили.
Майк Б

3
Я не кажу, що його рішення дає неправильні результати. Його рішення просто надзвичайно складне та неефективне.
Ян Джекеш

1
Так, прийняти відповідь, безумовно, не вдалося. Рішення Яна - приголомшливе! Як зауваження, я вважаю, що це (або незначна зміна) - це мій новий, улюблений тест кодування для розробників PHP, оскільки кількість відповідей на це питання, які насправді не працюють, неймовірна. Це було б чудовим способом зробити початкову фільтрацію. :-)
JamesG

знайшов регулярний вираз , що використовується в цьому розчині набагато більш повний: stackoverflow.com/questions/2559759 / ...
thoroc

2
Приємне рішення для простих випадків використання, і в більшості звичайних випадків цього достатньо, але прийняте рішення може обробляти більше випадків використання, наприклад, "simpleXML" може бути перетворений на "simple_xml", а не "simple_x_m_l"
Syone

35

Коротке рішення і може вирішити деякі складні випадки використання:

function decamelize($string) {
    return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string));
}

Може вирішувати всі ці випадки:

simpleTest => simple_test
easy => easy
HTML => html
simpleXML => simple_xml
PDFLoad => pdf_load
startMIDDLELast => start_middle_last
AString => a_string
Some4Numbers234 => some4_numbers234
TEST123String => test123_string
hello_world => hello_world
hello__world => hello__world
_hello_world_ => _hello_world_
hello_World => hello_world
HelloWorld => hello_world
helloWorldFoo => hello_world_foo
hello-world => hello-world
myHTMLFiLe => my_html_fi_le
aBaBaB => a_ba_ba_b
BaBaBa => ba_ba_ba
libC => lib_c

Ви можете перевірити цю функцію тут: http://syframework.alwaysdata.net/decamelize


@VivekVardhan, яку частину цього виразів ти не розумієш?
Syone

Ум, я вважаю, що рядки, що не містять верблюдів, є побічним ефектом, якщо рядок не у форматі верблюда, слід повернути оригінал. Infact, якщо ви надсилаєте 'simple_Text', ви отримуєте Fail: simple_Test => simple_Test [simple_test]. Рядок з нижньою обробкою має бути зроблений лише тоді, якщо лише оригінальна струна є справжньою ланцюжкою верблюда. Що ви думаєте про?
guideo

24

Порт із Рубі String#camelizeта String#decamelize.

function decamelize($word) {
  return preg_replace(
    '/(^|[a-z])([A-Z])/e', 
    'strtolower(strlen("\\1") ? "\\1_\\2" : "\\2")',
    $word 
  ); 
}

function camelize($word) { 
  return preg_replace('/(^|_)([a-z])/e', 'strtoupper("\\2")', $word); 
}

Один трюк, який вищезгадані рішення, можливо, пропустили - це модифікатор 'e', ​​який змушує preg_replaceоцінювати рядок заміни як PHP-код.


10
eПрапор preg_replaceє застарілим в PHP 5.5.
cdmckay

До цих пір вони також не в Ruby, а в бібліотеці інфлекторів Rails - підкреслити і підкреслити. api.rubyonrails.org/classes/ActiveSupport/Inflector.html
mahemoff

2
Це не вдається для "ThisIsATest". Здається, це не підтримує дві великі регістри поспіль.
OnaBai

Лише зауваження: ви можете скористатися lcfirst, щоб отримати першу букву в малі регістри, тоді вам не потрібно ^|або strlen.
Benubird

декамелізація без зневаги: gist.github.com/scones/e09c30e696246fda14578bcf8ab4910a
scones

23

Symfony Serializer компонент має CamelCaseToSnakeCaseNameConverter , який має два методи normalize()і denormalize(). Їх можна використовувати наступним чином:

$nameConverter = new CamelCaseToSnakeCaseNameConverter();

echo $nameConverter->normalize('camelCase');
// outputs: camel_case

echo $nameConverter->denormalize('snake_case');
// outputs: snakeCase

1
Остерігайся! $nameConverter->normalize('CamelCase')виводить _camel_caseу поточній версії 3.2 компонента серіалізатора Symfony.
spackmat

21

Більшість рішень тут відчувають важкі руки. Ось що я використовую:

$underscored = strtolower(
    preg_replace(
        ["/([A-Z]+)/", "/_([A-Z]+)([A-Z][a-z])/"], 
        ["_$1", "_$1_$2"], 
        lcfirst($camelCase)
    )
);

"CamelCASE" перетворюється на "camel_case"

  • lcfirst($camelCase) знизить перший символ (уникає перетвореного результату "CamelCASE", щоб почати з підкреслення)
  • [A-Z] знаходить великі літери
  • + буде розглядати кожну верхню верхню букву як слово (уникає перетворення "CamelCASE" на camel_C_A_S_E)
  • Другий шаблон і заміна призначені для ThoseSPECCases-> those_spec_casesзамістьthose_speccases
  • strtolower([…]) перетворює вихід на малі регістри

3
Але це також перетворює CamelCased на _camel_cased.
акме

1
це чудово - просто додайте субстрат, починаючи з char 1, щоб подолати цю проблему.
Оддман

4
Відмінник! Просто потрібно додати lcfirstфункцію до $ camelCase
Edakos

Прийнята відповідь буде обробляти: TestUPSClass в test_ups_class, тоді як це перетворить його в test_u_p_s_class, що потрібно пам’ятати.
Mazzy

Введення рядка, що починається з першого слова "allcaps", буде несподівано розділене цим рішенням через ucfirst()дзвінок. USADollarSymbolстає u_sa_dollar_symbol демо. Я не рекомендую це рішення, оскільки він повинен зробити два проходи через вхідну рядок з регулярним виразом - ознака нерафінованого шаблону.
mickmackusa

19

php не пропонує вбудованої функції для цього afaik, але ось що я використовую

function uncamelize($camel,$splitter="_") {
    $camel=preg_replace('/(?!^)[[:upper:]][[:lower:]]/', '$0', preg_replace('/(?!^)[[:upper:]]+/', $splitter.'$0', $camel));
    return strtolower($camel);

}

сплітер може бути вказаний у виклику функції, тож ви можете назвати його так

$camelized="thisStringIsCamelized";
echo uncamelize($camelized,"_");
//echoes "this_string_is_camelized"
echo uncamelize($camelized,"-");
//echoes "this-string-is-camelized"

2
Це не вдається для "ThisIsATest". Здається, це не підтримує дві великі регістри поспіль.
OnaBai

Напевно ви щось забули, оскільки друга заміна нічого не робить. Крім цього, ви можете легко зробити його unicode сумісним з mb_strtolowerі /uопцією preg_replace.
BODO

8

Потрібно пропустити через нього регулярний вираз, який відповідає кожній великій літері, за винятком випадків, якщо він знаходиться на початку, і замінити його підкресленням плюс цей лист. Рішення utf-8 таке:

header('content-type: text/html; charset=utf-8');
$separated = preg_replace('%(?<!^)\p{Lu}%usD', '_$0', 'AaaaBbbbCcccDdddÁáááŐőőő');
$lower = mb_strtolower($separated, 'utf-8');
echo $lower; //aaaa_bbbb_cccc_dddd_áááá_őőőő

Якщо ви не впевнені, у якому випадку знаходиться ваш рядок, краще спочатку перевірити його, оскільки цей код передбачає, що введення camelCaseзамість underscore_Caseабоdash-Case , тому, якщо на запісах є великі літери, вони додадуть їм підкреслення.

Прийнята відповідь від клетка є занадто складною імхо, і вона працює лише з латинськими символами. Я вважаю це дійсно поганим рішенням і цікаво, чому це взагалі було прийнято. Перетворення TEST123Stringв test123_stringне обов'язково є дійсною вимогою. Я досить тримав його простим і розділений ABCcccна a_b_ccccзамість того , ab_ccccтому що це не втратити інформацію так і в зворотному напрямку перетворення дасть ту ж саму рядок , яку ми почали. Навіть якщо ви хочете зробити це іншим способом, відносно легко написати для нього регулярний вираз з позитивним виглядом позаду (?<!^)\p{Lu}\p{Ll}|(?<=\p{Ll})\p{Lu}або двома регулярними виразками без огляду, якщо ви не експерт з регулярних виразів. Там немає необхідності , щоб розбити його на підрядка не кажучи вже про вибір між strtolowerі lcfirstде з використанням тільки strtolowerб абсолютно нормально.


Відповіді, що стосуються лише коду, мають низьку цінність для Stackoverflow, оскільки вони роблять дуже мало для навчання / розширення можливостей тисяч майбутніх дослідників.
mickmackusa

@mickmackusa Якщо дослідники дізнаються, як кодувати з SO, то у нас є серйозна проблема ...
inf3rno

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

Звичайно, я не маю повноважень видаляти публікацію з 8 оновлень. Якщо ви хочете, ви можете видалити свою відповідь, але було б не важко просто її покращити, видаливши непотрібні модифікатори шаблону та додавши пояснення. Особисті напади на мене не впливають.
mickmackusa

@mickmackusa Я не думаю, що я його також можу видалити. Не соромтесь редагувати його, якщо хочете.
inf3rno

6

Якщо ви шукаєте версію PHP 5.4 та пізнішу відповідь, тут є код:

function decamelize($word) {
      return $word = preg_replace_callback(
        "/(^|[a-z])([A-Z])/",
        function($m) { return strtolower(strlen($m[1]) ? "$m[1]_$m[2]" : "$m[2]"); },
        $word
    );

}
function camelize($word) {
    return $word = preg_replace_callback(
        "/(^|_)([a-z])/",
        function($m) { return strtoupper("$m[2]"); },
        $word
    );

} 

camelize produce "SmsSent" для sms_sent, потрібен lcfirst
mik3fly-4steri5k

4

Зовсім не фантазії, а просто та швидко, як пекло:

function uncamelize($str) 
{
    $str = lcfirst($str);
    $lc = strtolower($str);
    $result = '';
    $length = strlen($str);
    for ($i = 0; $i < $length; $i++) {
        $result .= ($str[$i] == $lc[$i] ? '' : '_') . $lc[$i];
    }
    return $result;
}

echo uncamelize('HelloAWorld'); //hello_a_world

++$iзамість того, $i++щоб зробити це також трохи швидше;)
Матьє Аміот

Відповіді, що стосуються лише коду, мають низьку цінність для Stackoverflow, оскільки вони роблять дуже мало для навчання / розширення можливостей тисяч майбутніх дослідників.
mickmackusa

4

"CamelCase" - "camel_case":

function camelToSnake($camel)
{
    $snake = preg_replace('/[A-Z]/', '_$0', $camel);
    $snake = strtolower($snake);
    $snake = ltrim($snake, '_');
    return $snake;
}

або:

function camelToSnake($camel)
{
    $snake = preg_replace_callback('/[A-Z]/', function ($match){
        return '_' . strtolower($match[0]);
    }, $camel);
    return ltrim($snake, '_');
}

Дякую. Я використовував перший підхід, але з дефісами для створенняthis-kind-of-output
thexpand

3

Версію, яка не використовує регулярний вираз, можна знайти в джерелі Alchitect :

decamelize($str, $glue='_')
{
    $counter  = 0;
    $uc_chars = '';
    $new_str  = array();
    $str_len  = strlen($str);

    for ($x=0; $x<$str_len; ++$x)
    {
        $ascii_val = ord($str[$x]);

        if ($ascii_val >= 65 && $ascii_val <= 90)
        {
            $uc_chars .= $str[$x];
        }
    }

    $tok = strtok($str, $uc_chars);

    while ($tok !== false)
    {
        $new_char  = chr(ord($uc_chars[$counter]) + 32);
        $new_str[] = $new_char . $tok;
        $tok       = strtok($uc_chars);

        ++$counter;
    }

    return implode($new_str, $glue);
}

2
Ось як виглядало б життя без регулярного
виразу

4
Хе, так. RegEx безумовно має свої переваги. :) Сировинна швидкість - не одна з них.
Даррелл Брогдон

чомусь отримали смішні результати з цим
mr1031011

Не працює для мене на основі цього рядка: "CamelCaseTestAAATestAA", повинен містити: "camel_case_test_a_a_a_test_a_a", має: "" camel_case_test_aest "...
Sybio

3

Отже, ось одноколісний:

strtolower(preg_replace('/(?|([a-z\d])([A-Z])|([^\^])([A-Z][a-z]))/', '$1_$2', $string));

Добре, але він конвертує лише перший вигляд, тому я рекомендую додати gмодифікатор до цього регулярного виразу.
акме

@acme, я використовую його без gмене, і він чудово працює для мене.
Seelts

Чомусь у моєму випадку мені довелося додати g. Але я не можу пригадати фразу, з якою я тестував.
акме


3

Laravel 5.6 пропонує дуже простий спосіб зробити це:

 /**
 * Convert a string to snake case.
 *
 * @param  string  $value
 * @param  string  $delimiter
 * @return string
 */
public static function snake($value, $delimiter = '_'): string
{
    if (!ctype_lower($value)) {
        $value = strtolower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value));
    }

    return $value;
}

Що це робиться: якщо він бачить, що в даному рядку є хоча б одна велика літера, для пошуку будь-якого символу ( ), за яким йде велика літера ( ) , використовується позитивний пошук . Потім він замінює знайдений символ його значенням, а потім роздільником ..(?=[A-Z])_


Ця функція, схоже, називається snake_case () і живе у глобальному просторі імен.
Wotuu

2

Прямий порт від рейок (за вирахуванням їх спеціального поводження для :: або абревіатур) був би

function underscore($word){
    $word = preg_replace('#([A-Z\d]+)([A-Z][a-z])#','\1_\2', $word);
    $word = preg_replace('#([a-z\d])([A-Z])#', '\1_\2', $word);
    return strtolower(strtr($word, '-', '_'));
}

Знаючи PHP, це буде швидше, ніж ручний розбір, що відбувається в інших відповідях, наведених тут. Недоліком є ​​те, що ви не можете вибрати, що використовувати як роздільник між словами, але це не було частиною питання.

Також перевірте відповідний вихідний код рейки

Зауважте, що це призначено для використання з ідентифікаторами ASCII. Якщо вам потрібно зробити це з символами, що знаходяться поза діапазоном ASCII, використовуйте модифікатор '/ u' для preg_matchвикористання mb_strtolower.


Ви можете, якщо просто додати параметр, який містить бажаний символ.
Fleshgrinder

2

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

Він перетворить усі слова із поданого рядка, що знаходяться у верблюді, у змію. Наприклад, "SuperSpecialAwesome, а також FizBuzz καιΚάτιΑκόμα" буде перетворено на "super_special_awesome, а також fizz_buzz και_κάτι_ακόμα".

mb_strtolower(
    preg_replace_callback(
        '/(?<!\b|_)\p{Lu}/u',
        function ($a) {
            return "_$a[0]";
        },
        'SuperSpecialAwesome'
    )
);

2

Yii2 мають різні функції, щоб зробити слово snake_case з CamelCase.

    /**
     * Converts any "CamelCased" into an "underscored_word".
     * @param string $words the word(s) to underscore
     * @return string
     */
    public static function underscore($words)
    {
        return strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $words));
    }


2

У мене була подібна проблема, але не вдалося знайти жодної відповіді, яка б задовольняла, як перетворити CamelCase в snake_case, уникаючи при цьому дублікатів або зайвих підкреслень _імен з підкресленнями або всіх скорочень.

Проблема полягає в наступному:

CamelCaseClass            => camel_case_class
ClassName_WithUnderscores => class_name_with_underscore
FAQ                       => faq

Написане нами рішення - це простий дзвінок з двох функцій, малий і маленький пошук та пошук та заміна послідовних малих літер:

strtolower(preg_replace("/([a-z])([A-Z])/", "$1_$2", $name));

На сьогоднішній день це найбільш стисле і корисне рішення ІМО.
Mr.Shan0

1
function camel2snake($name) {
    $str_arr = str_split($name);
    foreach ($str_arr as $k => &$v) {
        if (ord($v) >= 64 && ord($v) <= 90) { // A = 64; Z = 90
            $v = strtolower($v);
            $v = ($k != 0) ? '_'.$v : $v;
        }
    }
    return implode('', $str_arr);
}

Ви можете отримати доступ до символів безпосередньо за допомогою $name{$k}(або $name[$k]), що збільшить ваш код довше, але уникне великих витрат на перетворення його в масив і з нього.
BODO

Відповіді, що стосуються лише коду, мають низьку цінність для StackOverflow, оскільки вони погано працюють із розширенням можливостей / навчанням майбутніх дослідників. Ваше рішення, уникаючи витонченості виразки, дуже важке і вивернуте. Ви розбиваєтеся на кожен символ і здійснюєте багаторазові повторення викликів функцій. Позначати порожню рядок як клею не потрібно. Я б не розважав цим рішенням в одному зі своїх проектів, оскільки немає елегантності, низької читабельності та n кількості непотрібних викликів функцій.
mickmackusa

1

Найгірша відповідь тут була настільки близькою до того, щоб бути найкращим (використовуйте рамку). NO DON'T, просто подивіться на вихідний код. набагато надійнішим підходом (випробуваним) є бачення того, що використовує добре створена рамка. У рамках Zend є кілька фільтрів слів, які відповідають вашим потребам. Джерело .

ось пара методів, яку я адаптував із джерела.

function CamelCaseToSeparator($value,$separator = ' ')
{
    if (!is_scalar($value) && !is_array($value)) {
        return $value;
    }
    if (defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') == 1) {
        $pattern     = ['#(?<=(?:\p{Lu}))(\p{Lu}\p{Ll})#', '#(?<=(?:\p{Ll}|\p{Nd}))(\p{Lu})#'];
        $replacement = [$separator . '\1', $separator . '\1'];
    } else {
        $pattern     = ['#(?<=(?:[A-Z]))([A-Z]+)([A-Z][a-z])#', '#(?<=(?:[a-z0-9]))([A-Z])#'];
        $replacement = ['\1' . $separator . '\2', $separator . '\1'];
    }
    return preg_replace($pattern, $replacement, $value);
}
function CamelCaseToUnderscore($value){
    return CamelCaseToSeparator($value,'_');
}
function CamelCaseToDash($value){
    return CamelCaseToSeparator($value,'-');
}
$string = CamelCaseToUnderscore("CamelCase");

1

Існує бібліотека, яка забезпечує цю функціональність:

SnakeCaseFormatter::run('CamelCase'); // Output: "camel_case"

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


1

Це один із коротших способів:

function camel_to_snake($input)
{
    return strtolower(ltrim(preg_replace('/([A-Z])/', '_\\1', $input), '_'));
}

Відповіді, що стосуються лише коду, мають низьку цінність для Stackoverflow, оскільки вони роблять дуже мало для навчання / розширення можливостей тисяч майбутніх дослідників.
mickmackusa

1
@mickmackusa - тисячі майбутніх досліджень будуть зацікавлені у витонченому однокласнику та навчатимуть себе.
Teson

Мені шкода, що ти зайняв цю егоїстичну позицію. Ви, звичайно, могли б додати пояснення в той час, як вам знадобилося розробити та набрати цю відповідь. Ваша відповідь робить три функції дзвінка, але інші виконують завдання за два.
mickmackusa

1

Як де-камелізіровать без використання регулярного вираження:

function decamelize($str, $glue = '_') {
    $capitals = [];
    $replace  = [];

    foreach(str_split($str) as $index => $char) {
        if(!ctype_upper($char)) {
            continue;
        }

        $capitals[] = $char;
        $replace[]  = ($index > 0 ? $glue : '') . strtolower($char);
    }

    if(count($capitals) > 0) {
        return str_replace($capitals, $replace, $str);
    }

    return $str;
}

Редагування:

Як би я це зробив у 2019 році:

function toSnakeCase($str, $glue = '_') {
    return preg_replace_callback('/[A-Z]/', function ($matches) use ($glue) {
        return $glue . strtolower($matches[0]);
    }, $str);
}

І коли PHP 7.4 вийде:

function toSnakeCase($str, $glue = '_') {
    return preg_replace_callback('/[A-Z]/', fn($matches) => $glue . strtolower($matches[0]), $str);
}

1
Відповіді, що стосуються лише коду, мають низьку цінність для StackOverflow, оскільки вони погано працюють із розширенням можливостей / навчанням майбутніх дослідників. Зробити від 1 до 3 функціональних дзвінків по кожному символу в рядку, а потім ще два виклики функції після виконання циклу дуже важкі. Я б не розважав над рішенням з такою поганою економікою.
mickmackusa

Це приклад того, як це можна зробити без використання регулярних виразів, а не як це слід використовувати у виробництві, тому я не бачу вашої суті, крім того, що ви скаржитеся на відповідь 5y / o, що має одну нагоду, і навряд чи її побачать будь-які дослідники.
лисини

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

0

Використовувати класи фільтру Zend Word Фільтри легко :

<?php
namespace MyNamespace\Utility;

use Zend\Filter\Word\CamelCaseToUnderscore;
use Zend\Filter\Word\UnderscoreToCamelCase;

class String
{
    public function test()
    {
        $underscoredStrings = array(
            'simple_test',
            'easy',
            'html',
            'simple_xml',
            'pdf_load',
            'start_middle_last',
            'a_string',
            'some4_numbers234',
            'test123_string',
        );
        $camelCasedStrings = array(
            'simpleTest',
            'easy',
            'HTML',
            'simpleXML',
            'PDFLoad',
            'startMIDDLELast',
            'AString',
            'Some4Numbers234',
            'TEST123String',
        );
        echo PHP_EOL . '-----' . 'underscoreToCamelCase' . '-----' . PHP_EOL;
        foreach ($underscoredStrings as $rawString) {
            $filteredString = $this->underscoreToCamelCase($rawString);
            echo PHP_EOL . $rawString . ' >>> ' . $filteredString . PHP_EOL;
        }
        echo PHP_EOL . '-----' . 'camelCaseToUnderscore' . '-----' . PHP_EOL;
        foreach ($camelCasedStrings as $rawString) {
            $filteredString = $this->camelCaseToUnderscore($rawString);
            echo PHP_EOL . $rawString . ' >>> ' . $filteredString . PHP_EOL;
        }
    }

    public function camelCaseToUnderscore($input)
    {
        $camelCaseToSeparatorFilter = new CamelCaseToUnderscore();
        $result = $camelCaseToSeparatorFilter->filter($input);
        $result = strtolower($result);
        return $result;
    }

    public function underscoreToCamelCase($input)
    {
        $underscoreToCamelCaseFilter = new UnderscoreToCamelCase();
        $result = $underscoreToCamelCaseFilter->filter($input);
        return $result;
    }
}

----- підкресленняToCamelCase -----

simple_test >>> SimpleTest

легко >>> Легко

html >>> Html

simple_xml >>> SimpleXml

pdf_load >>> PdfLoad

start_middle_last >>> StartMiddleLast

a_string >>> AString

some4_numbers234 >>> Some4Numbers234

test123_string >>> Test123String

----- camelCaseToUnderscore -----

simpleTest >>> simple_test

легко >>> легко

HTML >>> html

simpleXML >>> simple_xml

PDFLoad >>> pdf_load

startMIDDLELast >>> start_middle_last

AString >>> a_string

Some4Numbers234 >>> some4_numbers234

TEST123String >>> test123_string


0

Бібліотека TurboCommons з відкритим кодом містить метод formatCase () загального призначення всередині класу StringUtils, який дозволяє конвертувати рядок у безліч загальних форматів справ, таких як CamelCase, UpperCamelCase, LowerCamelCase, snake_case, Title Case та багато іншого.

https://github.com/edertone/TurboCommons

Щоб використовувати його, імпортуйте файл phar у ваш проект та:

use org\turbocommons\src\main\php\utils\StringUtils;

echo StringUtils::formatCase('camelCase', StringUtils::FORMAT_SNAKE_CASE);

// will output 'camel_Case'

0
$str = 'FooBarBaz';

return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $str)); // foo_bar_baz

1
Відповіді, що стосуються лише коду, мають низьку цінність для StackOverflow, оскільки вони погано працюють із розширенням можливостей / навчанням майбутніх дослідників.
mickmackusa

-1

ЯКЩО ви можете почати з:

$string = 'Camel_Case'; // underscore or any other separator...

Тоді ви можете конвертувати в будь-який випадок лише за допомогою:

$pascal = str_replace("_", "", $string);
$snake = strtolower($string);

Або будь-які інші випадки:

$capitalized = str_replace("_", " ", $string); // Camel Case
$constant = strtoupper($string);               // CAMEL_CASE
$train = str_replace("_", "-", $snake);        // camel-case
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.