【问题标题】:PHP Optimizing a Very Long Switch Case StatementPHP优化一个很长的switch case语句
【发布时间】:2012-11-07 00:51:18
【问题描述】:

请看下面的代码

function GetAreaName($AreaCode)
{
  switch ($AreaCode) 
  {
    case 201: return 'New Jersey';
    case 202: return 'Washington';
    // this goes on till
    case 999: return '';
  }
}

假设AreaCode是998,那么它必须经历这么多案例! 我们如何优化这个功能? (使用数据库。)

我正在考虑构建一个数组并对其进行二进制搜索?但这意味着每次调用函数时都会重建数组?我们如何构建一次数组,将其缓存并在每次调用此函数时重复使用?

【问题讨论】:

  • 看起来太长了

标签: php arrays caching optimization switch-statement


【解决方案1】:

开关条件只评估一次:

在 switch 语句中,只对条件进行一次评估,并将结果与​​每个 case 语句进行比较。在 elseif 语句中,再次评估条件。如果您的条件比简单的比较更复杂和/或处于紧密循环中,则切换可能会更快。 ➫➫➫

不需要优化。但是,请阅读:
In PHP what's faster, big Switch statement, or Array key lookup

如果你想构建一个配置文件,你可以考虑这样的:

$areas = array
(
  1 => 'abc',
  2 => 'def',
  ..
);

然后简单比较:

if (!isset($areas[$some_code]))
{
  // do something
}
else
{
  // ok
}

【讨论】:

  • 这就是问题所在:“将结果与每个 case 语句进行比较”。
  • 大声笑,请先阅读答案的详细信息,亲爱的投票者!
  • @ajreal,Use array_key_exists,而不是isset
【解决方案2】:

试试下面的伪代码

$areas = array('201' => 'New Jersey',
                    '202' => 'Washington',
                    ......
                    ........
                    '999' => '');
function GetAreaName($AreaCode)
{


    if(isset($areas[$AreaCode])) {
        return $areas[$AreaCode];
    } else {
        // do something
    }

}

【讨论】:

  • 这会在每次调用时重建数组,这是问题要求避免的。
【解决方案3】:

为什么不直接使用哈希表?

class Area {

private $areaCodes = array(
            201 => 'New Jersey',
            202 => 'Washington',
            // this goes on till
            999 => '';
        );

    function getStateByAreaCode ($areaCode) {

        if (array_key_exists($areaCode, $this->areaCodes)) {
           return $this->areaCodes[$areaCode];
        } else {
           return false;
        }

    }
}

这样称呼它:

$area = new Area();
$city = $area->getStateByAreaCode(303);

只需将您的课程保存在一个文件中,并在需要时包含它。

您询问如何防止每次请求都创建数组: 通过将其放在课堂上,您至少可以保持清洁。从技术上讲,它仍然会在每个请求中创建,但除非您的阵列很大(比美国的区号大得多),否则它不应该造成性能问题。如果您担心每次有请求时都构建数组,那么请查看 APC 或 Zend Optimizer 之类的代码优化器。这实质上是获取 PHP 在运行时生成的字节码并缓存它。

【讨论】:

  • 你如何将它实现为一个函数?特别是,如何避免在每次调用时重建数组?
  • @erisco 我已经填写了代码,以便它可以在一个类中工作,并给出了一些关于使用 PHP 代码加速器进行优化的技巧。如果您不想在每次调用时都构建数组,那么您可以将其存储在数据库表中。但是,我认为与构建数组相比,连接到数据库的时间与发出请求的时间差别可以忽略不计。
【解决方案4】:

听起来您应该将其存储在数据库中。

但如果你不能这样做,要么将其抽象为某种配置文件并将其存储在某种持久对象中,要么只使用静态变量:

function foo($key) {
    static $cache = array(1 => 'abc', 2 => 'def', 3 => 'ghi');
    if (array_key_exists($key, $cache)) {
        return $cache[$key];
    } else {
        //Somehow signal an error (throw an exception, return boolean false, or something)
    }
}

在上面,$cache 只会存在一次。 (如果您知道这些值永远不会是 null,则可以使用 isset 而不是 array_key_exists。)

这不是很灵活,因为更改数据需要您编辑代码。您通常希望将数据和代码解耦。

这可能意味着将其存储在某种文件(json、xml、php 等)中,然后将其加载到某种结构中,您只创建一次。然后,您可以将该对象或数组传递到需要它的任何地方。 (或者,如果你想变得 hacky,你可以使用静态类。不过我建议不要这样做。)

【讨论】:

  • 似乎静态 $cache 仍然会为每个 php 页面请求构建。我环顾四周,发现这个stackoverflow.com/a/6062224/1809157 我可能需要将它存储在用户会话中,至少每个用户只构建一次。我认为它仍然不是最好的,它在我的 Web 应用程序的整个生命周期中只构建一次。
  • @user1809157 除非您使用apc 之类的东西,否则如果不联系某种外部源(会话从文件恢复;数据库需要连接;memcached 和家庭需要),就无法在请求之间持久保存它连接;等)。我发布的foo 的性能可能会比存储在会话中略好。
  • 嗯.. 好的,我现在就坚持使用您的解决方案。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-26
  • 1970-01-01
  • 2012-05-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多