Каков наилучший (самый дешевый) способ ввода сложных строк CamelCase?

У меня есть большое количество входящих фраз в реальном времени, которые должны быть преобразованы в alpha only - CamelCase словом и точкой разделения.

Это то, что я придумал, но есть ли более дешевый и быстрый способ выполнить эту задачу?

function FoxJourneyLikeACamelsHump(string $string): string {
$string = preg_replace("/[^[:alpha:][:space:]]/u", ' ', $string);
$string = ucwords($string);
$camelCase = preg_replace('/\s+/', '', $string);
return $camelCase;
}

// $expected = "ThQuCkBrWnFXJumpsVRThLZyDG";
$string = " Th3 qu!ck br0wn f0x jumps 0v3r th3 l@zy d0g. ";
$is = FoxJourneyLikeACamelsHump($string);

Результаты:

Приговоры: 100000000
Общее время: 40.844197034836 seconds
средний: 0.000000408

-1

Решение

Ваш код довольно эффективен. Вы все еще можете улучшить с помощью нескольких настроек:

  • Предоставить разделитель для ucwords так что искать не надо \t, \nи т. д., которые не будут в вашей строке после первого шага. В среднем это дает улучшение на 1%;
  • Вы можете выполнить последний шаг с заменой без регулярных выражений в пространстве. Это дает до 20% улучшения.

Код:

function FoxJourneyLikeACamelsHump(string $string): string {
$string = preg_replace("/[^[:alpha:][:space:]]/u", ' ', $string);
$string = ucwords($string, ' ');
$camelCase = str_replace(' ', '', $string);
return $camelCase;
}

Смотрите сроки для оригинальной и улучшенной версии на rextester.com.

Примечание: как вы использовали ucwordsВаш код не может быть надежно использован для юникодных строк в целом. Для этого вам нужно использовать такую ​​функцию, как mb_convert_case:

$string = mb_convert_case($string,  MB_CASE_TITLE);

… но это влияет на производительность.

3

Другие решения

Сравнивая с 3 альтернативами, я считаю, что ваш метод самый быстрый. Вот результаты 100 000 итераций:

array(4) {
["Test1"]=>
float(0.23144102096558)
["Test2"]=>
float(0.41140103340149)
["Test3"]=>
float(0.31215810775757)
["Test4"]=>
float(0.98423790931702)
}

куда Test1 твой, Test2 а также Test3 мои и Test4 из ответа @ RizwanMTuman (с исправлением).

Я думал, используя preg_split может дать вам возможность оптимизировать. В этой функции используется только 1 регулярное выражение, которое возвращает массив только альфа-элементов, к которым вы затем применяете ucfirst чтобы:

function FoxJourneyLikeACamelsHump_2(string $string): string {
return implode('', array_map(function($word) {
return ucfirst($word);
}, preg_split("/[^[:alpha:]]/", $string, null, PREG_SPLIT_NO_EMPTY)));
}

Это может быть дополнительно оптимизировано с помощью foreach вместо array_map (увидеть Вот):

function FoxJourneyLikeACamelsHump_3(string $string): string {
$validItems = preg_split("/[^[:alpha:]]/u", $string, null, PREG_SPLIT_NO_EMPTY);
$result = '';
foreach($validItems as $item) {
$result .= ucfirst($item);
}
return $result;
}

Это приводит меня к предположению, что 2 регулярных выражения и 1 ucwords быстрее, чем 1 регулярное выражение и несколько ucfirsts.

Полный тестовый скрипт:

<?php

// yours
function FoxJourneyLikeACamelsHump_1(string $string): string {
$string = preg_replace("/[^[:alpha:][:space:]]/u", ' ', $string);
$string = ucwords($string);
$camelCase = preg_replace('/\s+/', '', $string);
return $camelCase;
}

// mine v1
function FoxJourneyLikeACamelsHump_2(string $string): string {
return implode('', array_map(function($word) {
return ucfirst($word);
}, preg_split("/[^[:alpha:]]/", $string, null, PREG_SPLIT_NO_EMPTY)));
}

// mine v2
function FoxJourneyLikeACamelsHump_3(string $string): string {
$validItems = preg_split("/[^[:alpha:]]/u", $string, null, PREG_SPLIT_NO_EMPTY);
$result = '';
foreach($validItems as $item) {
$result .= ucfirst($item);
}
return $result;
}

// Rizwan with a fix
function FoxJourneyLikeACamelsHump_4(string $string): string {
$re = '/(?:\b|\d+)([a-z])|[\d+ +!.@]/';
$result = preg_replace_callback($re,function ($matches) {
return (isset($matches[1]) ? strtoupper($matches[1]) : '');
},$string);
return $result;
}// $expected = "ThQuCkBrWnFXJumpsVRThLZyDG";
$test1 = 0;
$test2 = 0;
$test3 = 0;
$test4 = 0;

$loops = 100000;

$time_start = microtime(true);
for($i=0; $i<$loops; $i++) {
$string = " Th3 qu!ck br0wn f0x jumps 0v3r th3 l@zy d0g. ";
$is = FoxJourneyLikeACamelsHump_1($string);
if($loops==1) echo $is."\n";
}
$time_end = microtime(true);
$test1 = $time_end - $time_start;

$time_start = microtime(true);
for($i=0; $i<$loops; $i++) {
$string = " Th3 qu!ck br0wn f0x jumps 0v3r th3 l@zy d0g. ";
$is = FoxJourneyLikeACamelsHump_2($string);
if($loops==1) echo $is."\n";
}
$time_end = microtime(true);
$test2 = $time_end - $time_start;

$time_start = microtime(true);
for($i=0; $i<$loops; $i++) {
$string = " Th3 qu!ck br0wn f0x jumps 0v3r th3 l@zy d0g. ";
$is = FoxJourneyLikeACamelsHump_3($string);
if($loops==1) echo $is."\n";
}
$time_end = microtime(true);
$test3 = $time_end - $time_start;

$time_start = microtime(true);
for($i=0; $i<$loops; $i++) {
$string = " Th3 qu!ck br0wn f0x jumps 0v3r th3 l@zy d0g. ";
$is = FoxJourneyLikeACamelsHump_4($string);
if($loops==1) echo $is."\n";
}
$time_end = microtime(true);
$test4 = $time_end - $time_start;

var_dump(array('Test1'=>$test1, 'Test2'=>$test2, 'Test3'=>$test3, 'Test4'=>$test4));
1

Вы можете попробовать это регулярное выражение:

(?:\b|\d+)([a-z])|[\d+ +!.@]

ОБНОВЛЕНИЕ ( Запустите это здесь )

Идея, приведенная выше, состоит в том, чтобы показать вам, как это должно работать в регулярных выражениях:

Ниже приведена реализация php приведенного выше регулярного выражения. Вы можете сравнить его с вашим, так как это позволяет выполнить операцию одной операцией замены:

<?php

$re = '/(?:\b|\d+)([a-z])|[\d+ +!.@]/';
$str = 'Th3 qu!ck br0wn f0x jumps 0v3r th3 l@zy d0g. ';
$subst=strtoupper('\\1');

$result = preg_replace_callback($re,function ($matches) {
return (isset($matches[1]) ? strtoupper($matches[1]) : '');
},$str);

echo $result;

?>

Regex Demo

1

Прежде чем думать о том, как улучшить производительность кода, вам нужно сначала создать работающий код. На самом деле вы пытаетесь создать код, который обрабатывает строки в кодировке utf8 (так как вы добавили модификатор u в ваш шаблон); но со строкой: liberté égalité fraternité ваш код возвращается Liberté égalité Fraternité вместо Liberté Égalité Fraternité так как ucwords (или же ucfirst) не умеют иметь дело с многобайтовые символы.

После попытки разных подходов (с preg_split а также preg_replace_callbackкажется, что это preg_match_all версия самая быстрая:

function FoxJourneyLikeACamelsHumpUPMA(string $string): string {
preg_match_all('~\pL+~u', $string, $m);
foreach ($m[0] as &$v) {
$v = mb_strtoupper(mb_substr($v, 0, 1)) . mb_strtolower(mb_substr($v, 1));
}
return implode('', $m[0]);
}

Очевидно, это медленнее, чем ваш исходный код, но мы не можем реально сравнить эти разные коды, так как ваш не работает.

0
По вопросам рекламы [email protected]