驼峰命名法转下划线哪个更快,
preg_replace()
还是ord()
?
我的猜测是,使用
ord()
会更快,因为 preg_replace()
可以做比需要的更多的事情。
function __autoload($class_name) {
$name = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $class_name));
require_once "some_dir/" . $name . ".php";
}
function __autoload($class_name) {
$class_name[0] = strtolower($class_name[0]);
$len = strlen($class_name);
for ($i = 0; $i < $len; ++$i) {
if (ord($class_name[$i]) > ord('A') && ord($class_name[$i]) < ord('Z')) {
$class_name[$i] = '_' . strtolower($class_name[$i]);
++$len;
++$i;
}
}
return $class_name;
}
代码示例取自 Convert CamelCase to under_score_case in php __autoload().
在 jensgram 的数组建议并找到
array_splice()
之后,我想出了以下内容。
function __autoload ($string) {
$string = str_split($string);
$pos = count($string);
while (--$pos > 0) {
$lower = strtolower($string[$pos]);
if ($string[$pos] === $lower) {
continue;
}
unset($string[$pos]);
array_splice($string, $pos, 0, array('_', $lower));
}
$string = implode('', $string);
return $string;
}
当我测试这些方法时,我会添加这个方法,但请随时告诉我你的结果。
我认为(而且我非常确定)preg_replace 方法会更快 - 但如果你想知道,为什么不做一个小基准测试,调用这两个函数 100000 次并测量时间?
(不是答案,但评论太长 - 将CW)
如果你要比较,你至少应该在
ord()
版本上优化一点。
$len = strlen($class_name);
$ordCurr = null;
$ordA = ord('A');
$ordZ = ord('Z');
for ($i = 0; $i < $len; ++$i) {
$ordCurr = ord($class_name[$i]);
// see if we have an uppercase character and replace
if ($ordCurr >= $ordA && $ordCurr <= $ordZ) {
$class_name[$i] = '_' . strtolower($class_name[$i]);
// increase length of class and position
++$len;
++$i;
}
}
此外,将名称压入堆栈(数组)并在末尾加入可能比字符串连接更有效。
但是 这值得首先进行优化/分析吗?
我的用例与OP略有不同,但我认为它仍然说明了 preg_replace 和手动字符串操作之间的区别。
$a = "16 East, 95 Street";
echo "preg: ".test_preg_replace($a)."\n";
echo "ord: ".test_ord($a)."\n";
$t = microtime(true);
for ($i = 0; $i < 100000; $i++) test_preg_replace($a);
echo (microtime(true) - $t)."\n";
$t = microtime(true);
for ($i = 0; $i < 100000; $i++) test_ord($a);
echo (microtime(true) - $t)."\n";
function test_preg_replace($s) {
return preg_replace('/[^a-z0-9_-]/', '-', strtolower($s));
}
function test_ord($s) {
$a = ord('a');
$z = ord('z');
$aa = ord('A');
$zz = ord('Z');
$zero = ord('0');
$nine = ord('9');
$us = ord('_');
$ds = ord('-');
$toret = '';
for ($i = 0, $len = strlen($s); $i < $len; $i++) {
$c = ord($s[$i]);
if (($c >= $a && $c <= $z)
|| ($c >= $zero && $c <= $nine)
|| $c == $us
|| $c == $ds)
{
$toret .= $s[$i];
}
elseif ($c >= $aa && $c <= $zz)
{
$toret .= chr($c + $a - $aa); // strtolower
}
else
{
$toret .= '-';
}
}
return $toret;
}
结果是
0.42064881324768
2.4904868602753
所以 preg_replace 方法要优越得多。此外,字符串连接比插入数组并使其内爆稍微快一些。
如果您只想将驼峰式大小写转换为下划线,您可能可以编写一个比 ord 或 preg_replace 更高效的函数来执行此操作,所需时间比分析它们所需的时间要短。
我使用以下四个函数编写了一个基准测试,我发现在 Magento 中实现的函数是最快的(Test4):
测试1:
/**
* @see: http://www.paulferrett.com/2009/php-camel-case-functions/
*/
function fromCamelCase_1($str)
{
$str[0] = strtolower($str[0]);
return preg_replace('/([A-Z])/e', "'_' . strtolower('\\1')", $str);
}
测试2:
/**
* @see: http://stackoverflow.com/questions/3995338/phps-preg-replace-versusvs-ord#answer-3995435
*/
function fromCamelCase_2($str)
{
// lowercase first letter
$str[0] = strtolower($str[0]);
$newFieldName = '';
$len = strlen($str);
for ($i = 0; $i < $len; ++$i) {
$ord = ord($str[$i]);
// see if we have an uppercase character and replace
if ($ord > 64 && $ord < 91) {
$newFieldName .= '_';
}
$newFieldName .= strtolower($str[$i]);
}
return $newFieldName;
}
测试3:
/**
* @see: http://www.paulferrett.com/2009/php-camel-case-functions/#div-comment-133
*/
function fromCamelCase_3($str) {
$str[0] = strtolower($str[0]);
$func = create_function('$c', 'return "_" . strtolower($c[1]);');
return preg_replace_callback('/([A-Z])/', $func, $str);
}
测试4:
/**
* @see: http://svn.magentocommerce.com/source/branches/1.6-trunk/lib/Varien/Object.php :: function _underscore($name)
*/
function fromCamelCase_4($name) {
return strtolower(preg_replace('/(.)([A-Z])/', "$1_$2", $name));
}
使用字符串“getExternalPrefix”1000次的结果:
fromCamelCase_1: 0.48158717155457
fromCamelCase_2: 2.3211658000946
fromCamelCase_3: 0.63665509223938
fromCamelCase_4: 0.18188905715942
使用“WAytGLPqZltMfHBQXClrjpTYWaEEkyyu”等随机字符串 1000 次的结果:
fromCamelCase_1: 2.3300149440765
fromCamelCase_2: 4.0111720561981
fromCamelCase_3: 2.2800230979919
fromCamelCase_4: 0.18472790718079
使用测试字符串我得到了不同的输出 - 但这不应该出现在您的系统中:
original:
MmrcgUmNfCCTOMwwgaPuGegEGHPzvUim
last test:
mmrcg_um_nf_cc_to_mwwga_pu_geg_eg_hpzv_uim
other tests:
mmrcg_um_nf_c_c_t_o_mwwga_pu_geg_e_g_h_pzv_uim
正如您在时间戳中看到的 - 最后一个测试在两个测试中具有相同的时间:)