快速计算案例

时间:2009-03-20 20:50:14

标签: php optimization

我有大量的字符串要在php中处理。我想“修复”它们作为标题大小写(使用ucwords(strtolower($str))),但前提是它们都是大写或全部小写。如果它们已经是混合的情况,我只是将它们保留原样。

检查此问题的最快方法是什么?似乎for通过字符串将是一种相当缓慢的方式。

这就是我所拥有的,我认为这会太慢了:

function fixCase($str)
{
    $uc = 0;
    $lc = 0;
    for($i=0;$i<strlen($str);$i++)
    {
        if ($str[$i] >= 'a' && $str[$i] <= 'z')
            $lc++;
        else if ($str[$i] >= 'A' && $str[$i] <= 'Z')
            $uc++;
    }

    if ($uc == 0 || $lc == 0)
    {
        return ucwords(strtolower($str));
    }
}

7 个答案:

答案 0 :(得分:6)

只使用字符串比较(区分大小写)

function fixCase($str)
{
  if ( 
       (strcmp($str, strtolower($str)) === 0) || 
       (strcmp($str, strtoupper($str)) === 0) ) 
  {
    $str = ucwords(strtolower($str));
  }

  return $str;
}

答案 1 :(得分:1)

不会有任何惊人的优化,因为根据问题的本质,你需要看每个角色。

就个人而言,我会用这种算法循环遍历字符串的字符:

  • 查看字符串中的第一个字符,设置一个变量,指示它是大写还是小写。
  • 现在按顺序检查每个字符。如果你到达字符串的末尾,并且它们与第一个字符的情况相同,请根据需要修复字符串的大小写。
  • 如果任何字符与第一个字符的情况不同,请中断循环并返回字符串。

编辑:实际代码,我认为这与您将获得的一样好。

// returns 0 if non-alphabetic char, 1 if uppercase, 2 if lowercase
function getCharType($char)
{
    if ($char >= 'A' && $char <= 'Z')
    {
        return 1;
    }
    else if ($char >= 'a' && $char <= 'z')
    {
        return 2;
    }
    else
    {
        return 0;
    }
}

function fixCase($str)
{
    for ($i = 0; $i < strlen($str); $i++)
    {
        $charType = getCharType($str[$i]);
        if ($charType != 0)
        {
            $firstCharType = $charType;
            break;
        }
    }

    for ($i = $i + 1; $i < strlen($str); $i++)
    {
        $charType = getCharType($str[$i]);
        if ($charType != $firstCharType && $charType != 0)
        {
            return $str;
        }
    }

    if ($firstCharType == 1) // uppercase, need to convert to lower first
    {
        return ucwords(strtolower($str));
    }
    else if ($firstCharType == 2) // lowercase, can just ucwords() it
    {
        return ucwords($str);
    }
    else // there were no letters at all in the string, just return it
    {
        return $str;
    }
}

答案 2 :(得分:1)

您可以尝试我发布here

的字符串案例测试功能
function getStringCase($subject)
{
    if (!empty($subject))
    {
        if (preg_match('/^[^A-Za-z]+$/', $subject))
            return 0;   // no alphabetic characters
        else if (preg_match('/^[^A-Z]+$/', $subject))
            return 1;   // lowercase
        else if (preg_match('/^[^a-z]+$/', $subject))
            return 2;   // uppercase
        else
            return 3;   // mixed-case
    }
    else
    {
        return 0;   // empty
    }
}

答案 3 :(得分:1)

如果您想避免修复已经混合大小写的字符串的原因是为了提高效率,那么您可能会浪费时间,无论当前条件如何都要转换每个字符串:

function fixCase($str)
{
    return ucwords(strtolower($str));
}

如果它比字符串的接受答案慢得多,那么我会非常惊讶你通常想要标题的长度,这是你需要担心的一个条件。

但是,如果有充分的理由避免转换已经混合的字符串,例如你想在套管中保留一些预期的含义,那么是的,jcinacio的答案当然是最简单和最有效的。

答案 4 :(得分:0)

检查string = lowercase(string)或string = uppercase(string)是否更容易,如果是,则保留它。否则执行您的操作。

答案 5 :(得分:0)

我决定对迄今为止提出的2个答案和我原来的解决方案进行测试。我不会想到结果会以这种方式结果,但我想原生方法比所有人都要快得多。

代码:

function method1($str)
{
    if (strcmp($str, strtolower($str)) == 0)
    {
        return ucwords($str);
    }
    else if (strcmp($str, strtoupper($str)) == 0)
    {
        return ucwords(strtolower($str));
    }
    else
    {
        return $str;
    }
}

// returns 0 if non-alphabetic char, 1 if uppercase, 2 if lowercase
function getCharType($char)
{
    if ($char >= 'A' && $char <= 'Z')
    {
        return 1;
    }
    else if ($char >= 'a' && $char <= 'z')
    {
        return 2;
    }
    else
    {
        return 0;
    }
}

function method2($str)
{
    for ($i = 0; $i < strlen($str); $i++)
    {
        $charType = getCharType($str[$i]);
        if ($charType != 0)
        {
            $firstCharType = $charType;
            break;
        }
    }

    for ($i = $i + 1; $i < strlen($str); $i++)
    {
        $charType = getCharType($str[$i]);
        if ($charType != $firstCharType && $charType != 0)
        {
            return $str;
        }
    }

    if ($firstCharType == 1) // uppercase, need to convert to lower first
    {
        return ucwords(strtolower($str));
    }
    else if ($firstCharType == 2) // lowercase, can just ucwords() it
    {
        return ucwords($str);
    }
    else // there were no letters at all in the string, just return it
    {
        return $str;
    }
}

function method0($str)
{
        $uc = 0;
        $lc = 0;
        for($i=0;$i<strlen($str);$i++)
        {
                if ($str[$i] >= 'a' && $str[$i] <= 'z')
                        $lc++;
                else if ($str[$i] >= 'A' && $str[$i] <= 'Z')
                        $uc++;
        }

        if ($uc == 0 || $lc == 0)
        {
                return ucwords(strtolower($str));
        }
}


function test($func,$s)
{
    $start = gettimeofday(true);
    for($i = 0; $i < 1000000; $i++)
    {
        $s4 = $func($s);
    }
    $end = gettimeofday(true);
    echo "$func Time: " . ($end-$start) . " - Avg: ".sprintf("%.09f",(($end-$start)/1000000))."\n";
}


$s1 = "first String";
$s2 = "second string";
$s3 = "THIRD STRING";

test("method0",$s1);
test("method0",$s2);
test("method0",$s3);

test("method1",$s1);
test("method1",$s2);
test("method1",$s3);

test("method2",$s1);
test("method2",$s2);
test("method2",$s3);

结果:

method0 Time: 19.2899270058 - Avg: 0.000019290
method0 Time: 20.8679389954 - Avg: 0.000020868
method0 Time: 24.8917310238 - Avg: 0.00002489   
method1 Time: 3.07466816902 - Avg: 0.000003075
method1 Time: 2.52559089661 - Avg: 0.000002526
method1 Time: 4.06261897087 - Avg: 0.000004063
method2 Time: 19.2718701363 - Avg: 0.000019272
method2 Time: 35.2485661507 - Avg: 0.000035249
method2 Time: 29.3357679844 - Avg: 0.000029336

答案 6 :(得分:0)

请注意,只要有重音符号或变音符号,任何只看[A-Z]的内容都会出错。如果结果不正确,优化速度是没有意义的(嘿,如果结果不一定正确,它可以为你写一个非常快速的实现...)