CamelCase复杂输入字符串的最佳(最便宜)方式是什么?

时间:2017-04-08 02:40:50

标签: php regex php-7 camelcasing php-7.1

我有大量实时传入的短语需要通过单词和分割点转换为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

4 个答案:

答案 0 :(得分:3)

您的代码效率很高。您仍然可以通过一些调整来改进:

  • 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一样,您的代码通常无法可靠地用于unicode字符串。为了弥补这一点,您需要使用mb_convert_case之类的函数:

$string = mb_convert_case($string,  MB_CASE_TITLE);

......但这会对性能产生影响。

答案 1 :(得分:1)

你可以试试这个正则表达式:

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

UPDTAE(Run it here

上面的想法是向你展示在正则表达式中应该如何工作:

以下是上述正则表达式的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

答案 2 :(得分:1)

对3种替代方案进行基准测试,我相信你的方法是最快的。以下是100,000次迭代的结果:

ID

array(4) { ["Test1"]=> float(0.23144102096558) ["Test2"]=> float(0.41140103340149) ["Test3"]=> float(0.31215810775757) ["Test4"]=> float(0.98423790931702) } 是你的Test1Test2是我的,而Test3来自@ RizwanMTuman的答案(有修复)。

我认为使用Test4可能会为您提供优化机会。在此函数中,仅使用1个正则表达式,并返回仅将您应用于preg_split的alpha项目的数组:

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(参见http://en.cppreference.com/w/cpp/language/template_specialization)可以进一步优化这一点:

array_map

这使我推测2个正则表达式和1个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; } 比1个正则表达式和多个ucwords更快。

完整的测试脚本:

ucfirst

答案 3 :(得分:0)

在考虑提高代码性能之前,首先需要构建一个有效的代码。实际上你正在尝试构建一个处理utf8编码字符串的代码(因为你在你的模式中添加了u修饰符);但是使用字符串liberté égalité fraternité,您的代码会返回Liberté égalité Fraternité而不是Liberté Égalité Fraternité,因为ucwords(或ucfirst)无法处理multibyte characters

尝试了不同的方法(使用preg_splitpreg_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]);
}

显然,它比你的初始代码慢,但我们无法真正比​​较这些不同的代码,因为你的代码不起作用。