如何优化if else if语句,其中前一个ifs不在循环中使用?

时间:2013-08-19 19:56:24

标签: php

这是假设的代码,假设我有以下内容:

假设我有一个数组,它在这个示例问题中有很多数据,整数,但是它可以在if语句中以某种方式对任何类型的数据进行排序。

$a = array(0,0,0,1,1,1,1,1,1,2,2,2,2,3,3,...,9,9,9);

假设我有一个包含许多if else if语句的for循环,那些可以有任何做某事的标准。

for($i=0; i<count($a); i++) {
    // these if statements can be anything and may or may not be related with $a
    if($a[$i] == 0 && $i < 10) { 
        // do something
    }
    else if($a[$i] == 1 && $i < 20) {
        // do something
    }
    else if($a[$i] == 2) {
        // do something
    }
    else if($a[$i] == 3) {
        // do something
    }

    // and so on
}

现在的问题是,在第一次if语句迭代完成后,它从未被使用过。一旦for循环开始使用下一个if语句,就不需要再次评估前面的if语句。它可以使用第一个if语句n次等等。

有没有办法优化它,所以它不必遍历所有以前的if else if语句,因为它循环数据?记住,数据可以是任何东西,if语句可以是各种条件。

是否存在一种范式转换,我没有看到,这应该如何编码以提供最佳性能?

7 个答案:

答案 0 :(得分:1)

您可以利用call_user_func_array。您需要构建一个存储方法的类来调用以执行语句。考虑这样一个类:

class MyStatements {
    public function If0($a, $i) {
        if($a[$i] == 0 && $i < 10) {
            // do something
        }
    }

    public function If1($a, $i) {
        if($a[$i] == 1 && $i < 20) {
            // do something
        }
    }
}
然后你可以做这样的事情:

$stmts = new MyStatements();
for($i = 0; i < count($a); i++) {
    call_user_func_array(array($stmts, 'If' . strval($i)), array($a, $i));
}

答案 1 :(得分:0)

将for语句分解为多个for语句。对于您的示例代码:

for($i=0; i<10; i++) {
    if($a[$i] == 0) {
        //do something
    }
}

for($i=0; i<20; i++) {
    if($a[$i] == 1) {
        //do something
    }
}

for($i=0; $i<count($a); $i++) {
    if($a[$i] == 2) {
        // do something
    }
    else if($a[$i] == 3) {
        // do something
    }
}

//etc...

答案 2 :(得分:0)

PHP使用一种称为“短路评估”的东西,就像许多其他现代语言一样。这意味着一旦布尔表达式被确定为真或假,表达式的其余部分将不会被评估。

因此,您可以引入新的布尔值(可能是它们的数组)来跟踪是否已经执行了一段代码,如果已经执行了,则将其设置为false。然后使用此布尔值作为“if”表达式中的第一个条件。 PHP将识别此值的值设置为false,并忽略该子句的其余部分。这是一条非常简单的路线,可以保持您的代码大部分按现在的方式构建。

答案 3 :(得分:0)

我认为你正在转动你的车轮。

如果你有大量数据,那么很可能是数据源慢而不是服务器端计算。

如果您执行任何操作,则应将数据分解为块并一次运行部分。如果您注意到服务器上的加载时间较慢或负载较差,则只需执行此操作。

异步连接允许您轻松地执行此操作,使用ajax可以连接到服务器,提取有限的数据块,处理它,然后在客户端浏览器中显示后,运行下一个块。无论何时使用查询大量数据的网站(即:facebook),都可以这样做。

但同样,不要过度思考这一点。你真的不需要让你的程序更复杂。如果你真的想要一个金星,你可以创建一个面向对象的类,为你处理所有这些,但我不会深入研究。

答案 4 :(得分:0)

如果您使用的是PHP 5.3+,则可以使用anonymous functions

$a = array(0,0,0,1,1,1,1,1,1,2,2,2,2,3,3,9,9,9);

$dispatch = array(
    0=>function() { echo "0"; },
    1=>function() { echo "1"; },
    2=>function() { echo "2"; },
    3=>function() { echo "3"; },
    9=>function() { echo "9"; }
);

foreach ($a as $i)
{
    $dispatch[$i]();
}

在PHP 5.3之前,您必须使用映射来表示函数名称,但底部也适用于PHP 5.3+。

$a = array(0,0,0,1,1,1,1,1,1,2,2,2,2,3,3,9,9,9);

function foo0()  { echo "0"; }
function foo1()  { echo "1"; }
function foo2()  { echo "2"; }
function foo3()  { echo "3"; }
function foo9()  { echo "9"; }

$dispatch = array(
    0=>"foo0",
    1=>"foo1",
    2=>"foo2",
    3=>"foo3",
    9=>"foo9"
);

foreach ($a as $i)
{
    $dispatch[$i]();
}

上面的代码更快,但效率不高。要提高性能,您必须在$ dispatch数组中删除键查找,并在每次$ a [#]的值更改时向前移动。这假设您的$ dispatch数组与输入数组匹配。如果$ dispatch数组非常大,你只会获得性能提升。

$a = array(0,0,0,1,1,1,1,1,1,2,2,2,2,3,3,9,9,9);

function foo0()  { echo "0"; }
function foo1()  { echo "1"; }
function foo2()  { echo "2"; }
function foo3()  { echo "3"; }
function foo9()  { echo "9"; }

$dispatch = array(
    0=>"foo0",
    1=>"foo1",
    2=>"foo2",
    3=>"foo3",
    9=>"foo9"
);

reset($dispatch);
$foo = (string)current($dispatch);
$last = 0;
foreach ($a as $i)
{
    $foo();
    if($i != $last)
    {
        $foo = (string)next($dispatch);
        $last = $i;
    }
}

这应该尽可能高效。

答案 5 :(得分:0)

我不确定这与The Solution有什么不同,但我想我会把它扔出去。

function func1 () {
    echo "hi\n";
}
function func2 () {
    echo "bye\n";
}
$functionList = array (
    0 => "func1",
    1 => "func2"
);
$a = array(0,0,0,1,1,1,1,1,1,2,2,2,2,3,3,9,9,9);
$len = count($a);
for($i = 0; $i < $len; $i++) {
    if (isset($functionList[$i])) {
        call_user_func($functionList[$i]);
    }
}

我明确设置了$functionList的键,因为OP表示它们并不总是数字。也许前2-3个作业可以包装成一个类。

答案 6 :(得分:0)

这个详细的解决方案将阻止任何if条件在评估为false后运行,并且不会多次迭代相同的$i值,除非它转换到下一个循环。

for($i=0; i<count($a); i++) {
    if($firstCondition) {
        //do something
    } else {
        break;
    }
}

for($i; i<count($a); i++) {
    if($secondCondition) {
        //do something
    } else {
        break;
    }
}