preg_replace () против php (vs.) ord () - PullRequest
       16

preg_replace () против php (vs.) ord ()

1 голос
/ 22 октября 2010

Что быстрее, для camelCase, чтобы подчеркнуть;использование preg_replace () или использование ord ()?

Я предполагаю, что метод с использованием ord будет быстрее, поскольку preg_replace может сделать гораздо больше, чем нужно.

<?php
function __autoload($class_name){
    $name = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $class_name));
    require_once("some_dir/".$name.".php");
}
?>

ИЛИ

<?php
function __autoload($class_name){
// lowercase first letter
$class_name[0] = strtolower($class_name[0]);

$len = strlen($class_name);
for ($i = 0; $i < $len; ++$i) {
    // see if we have an uppercase character and replace
    if (ord($class_name[$i]) > ord('A') && ord($class_name[$i]) < ord('Z')) {
        $class_name[$i] = '_' . strtolower($class_name[$i]);
        // increase length of class and position
        ++$len;
        ++$i;
    }
}

return $class_name;
}
?>

заявление об отказе - примеры кода, взятые из StackOverflowQuestion 1589468 .

редактирование, после jensgram предложение массива и поиск array_splice я придумал следующее:

<?php
function __autoload ($string)// actually, function camel2underscore
{
$string  =  str_split($string);
$pos     =  count( $string );
while ( --$pos > 0 )
{
    $lower  =  strtolower( $string[ $pos ] );
    if ( $string[ $pos ] === $lower )
    {
        // assuming most letters will be underscore this should be improvement
        continue;
    }
    unset( $string[ $pos ] );
    array_splice( $string , $pos , 0 , array( '_' , $lower ) );
}
$string  =  implode( '' , $string );
return $string;
}
// $pos could be avoided by using the array key, something i might look into later on.
?>

Когда я буду тестировать эти методы, я добавлю этот, но не стесняйтесь сообщать мне свои результаты в любое время; p

Ответы [ 5 ]

2 голосов
/ 22 октября 2010

Я думаю (и я почти уверен), что метод preg_replace будет быстрее - но если вы хотите знать, почему бы вам не выполнить небольшой тест, вызывающий обе функции 100000 раз и измерить время?

1 голос
/ 30 декабря 2010

Мой сценарий использования немного отличался от 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 значительно лучше. Кроме того, конкатенация строк немного быстрее, чем вставка в массив и его развертывание.

1 голос
/ 22 октября 2010

(не ответ, но слишком долго, чтобы быть комментарием - будет 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;
    }
}

Кроме того, помещение имени в стек (массив) и объединение в конце может оказаться более эффективным, чем конкатенация строк.

НО Стоит ли вообще оптимизировать / профилировать?

0 голосов
/ 02 сентября 2011

Я написал эталонный тест, используя следующие четыре функции, и выяснил, что тот, который реализован в Magento, является самым быстрым (это Test4):

Test1:

/**
 * @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);
}

Test2:

/**
 * @see: /4016269/pregreplace-protiv-php-vs-ordanswer-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;
}

Test3:

/**
 * @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);
}

Test4:

/**
 * @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

Как вы видите на отметках времени - последний тест имеет одинаковое время в обоих тестах:)

0 голосов
/ 22 октября 2010

Если все, что вы хотите сделать, это преобразовать регистр верблюдов в подчеркивания, вы, вероятно, можете написать более эффективную функцию, чем ord или preg_replace, за меньшее время, чем требуется для их профилирования.

...