-1

I have the following functions:

function dashesToCamelCase($string)
{
    return str_replace(' ', '', ucwords(str_replace('-', ' ', $string)));
}

function camelCaseToDashes($string) {
    //This method should not have Regex
    $string = preg_replace('/\B([A-Z])/', '-$1', $string);
    return strtolower($string);
}

And here is a Test:

$testArray = ['UserProfile', 'UserSettings', 'Settings', 'SuperLongString'];

foreach ($testArray as $testData) {
    $dashed = camelCaseToDashes($testData);
    $orignal = dashesToCamelCase($dashed);
    echo '<pre>' . $dashed . ' | ' . $orignal . '</pre>';
}

This is the expected output:

user-profile      | UserProfile
user-settings     | UserSettings
settings          | Settings
super-long-string | SuperLongString

Now my Question: The method camelCaseToDashes now is using Regex. Can you imagine a better (faster) implementation without Regex?

Christian Gollhardt
  • 16,510
  • 17
  • 74
  • 111
  • 1
    This is a premature optimization – maček Aug 03 '14 at 00:08
  • 1
    Regex implementations are already optimized using the best built-in functions available or even with some under the hood optimization written as a PHP module, with C code. You don't need to reinvent the wheel... – Henrique Barcelos Aug 03 '14 at 00:39
  • Thanks @HenriqueBarcelos, just thought this is not a "Regular Problem", because so many people say: Avoid Regex. But this example (and the according answers with benchmarks) opend my eyes. – Christian Gollhardt Aug 03 '14 at 00:42

3 Answers3

3

You should really first check a profiler graph before optimizing the wrong thing.

enter image description here

Visualize the actual execution time your preg_replace takes.

Replacing a regex with various PHP string function workarounds is not usually an optimization.

mario
  • 144,265
  • 20
  • 237
  • 291
1

Try this:

$text = 'CamelCaseString';

$result = '';
for ($i = 0; $i < strlen($text); $i++) {
    $result .= $i > 0 && ord($text[$i]) >= 64 && ord($text[$i]) <= 90 ? '-'.$text[$i] : $text[$i];
}

var_dump(strtolower($result));

You can create a benchmark to see performance of each solution.

Actually, according to my benchmark, solution with regular expression seems to be roughly 10× faster:

$ php test2.php regex: 0.41732287406921 without regex: 3.5226600170135

I guess, that regular expression would be better, because it's implemented in C. My algorithm is implemented in PHP, which has significantly worse performance. With few optimizations I was able to improve time of 100,000 iterations of my algorithm to 2.5 second (compare to 0.4 second of 100,000 iterations of regexp).

Improved version:

$text = 'CamelCaseString';

$result = '';
$lenght = strlen($text);
for ($i = 0; $i < $lenght; $i++) {
    $ord = ($text[$i]);
    $result .= $i > 0 && $ord >= 64 && $ord <= 90 ? '-'.$text[$i] : $text[$i];
}

$ php test2.php regex: 0.40657687187195 without regex: 2.5361099243164

Also interesting thing: regexp solution profile

As you can see on a profile of your function, function preg_replace takes only 12 % of total time, strtolower takes under 1 %. There is no other code in the function regex. But it's possible that this is overhead of Xdebug. Profile was visualized by qCacheGrind.

David Ferenczy Rogožan
  • 23,966
  • 9
  • 79
  • 68
  • Thanks for your Response. I have inserted a `ltrim ($result,'-')` and did benchmarked it. Your method takes twice times then with regex. But thanks for the solution. – Christian Gollhardt Aug 03 '14 at 00:14
  • 1
    It was my fault, but I have already fixed that, no need for `ltrim` now. I think your regexp solution is good enough :) – David Ferenczy Rogožan Aug 03 '14 at 00:38
  • Would wish to double upvote, because you invest so much time for this question, and have done 3 edits now, each 1 upvote worth for me :) You realy have helped me out :) Even learnt the new thing, that you can access a string as a char array and get the char code :) – Christian Gollhardt Aug 03 '14 at 00:57
  • 1
    Great! It's really pleasing to hear that I help someone and therefore it's worth to invest my time to that. And also I can learn something new doing that. For example that regular expressions have quite good performance. Also I really advice you to use Xdebug for (but not only) profiling. You can visualize generated profile with for example [kCacheGrind](http://kcachegrind.sourceforge.net), [qCacheGrind](http://sourceforge.net/projects/qcachegrindwin/) or [XCallGraph](http://sourceforge.net/projects/xcallgraph/) to see how much time each function takes in your script. – David Ferenczy Rogožan Aug 03 '14 at 01:22
1

If you want a ridiculous gain try this:

function dashesToCamelCase2($string) {
    return strtr(ucwords(strtr($string, '-', ' ')), ' ', '');
}

function camelCaseToDashes2($string) {
    return strtolower(preg_replace('/(?=[A-Z])\B/', '-', $string));
}
Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125