preg_replace() 与 ord()

问题描述 投票:0回答:5

驼峰命名法转下划线哪个更快,

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;
}

当我测试这些方法时,我会添加这个方法,但请随时告诉我你的结果。

php function comparison performance
5个回答
2
投票

我认为(而且我非常确定)preg_replace 方法会更快 - 但如果你想知道,为什么不做一个小基准测试,调用这两个函数 100000 次并测量时间?


1
投票

(不是答案,但评论太长 - 将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;
    }
}

此外,将名称压入堆栈(数组)并在末尾加入可能比字符串连接更有效。

但是 这值得首先进行优化/分析吗?


1
投票

我的用例与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 &lt 100000; $i++) test_preg_replace($a);
echo (microtime(true) - $t)."\n";
$t = microtime(true);
for ($i = 0; $i &lt 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 &lt;= $z) 
            || ($c >= $zero && $c &lt;= $nine)
            || $c == $us 
            || $c == $ds)
        {   
            $toret .= $s[$i];
        }   
        elseif ($c >= $aa && $c &lt;= $zz)
        {   
            $toret .= chr($c + $a - $aa); // strtolower
        }   
        else
        {   
            $toret .= '-';
        }   
    }   
    return $toret;
}

结果是

0.42064881324768
2.4904868602753

所以 preg_replace 方法要优越得多。此外,字符串连接比插入数组并使其内爆稍微快一些。


0
投票

如果您只想将驼峰式大小写转换为下划线,您可能可以编写一个比 ord 或 preg_replace 更高效的函数来执行此操作,所需时间比分析它们所需的时间要短。


0
投票

我使用以下四个函数编写了一个基准测试,我发现在 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

正如您在时间戳中看到的 - 最后一个测试在两个测试中具有相同的时间:)

© www.soinside.com 2019 - 2024. All rights reserved.