【问题标题】:How can I make a loop faster?如何使循环更快?
【发布时间】:2019-06-29 07:01:56
【问题描述】:

我有一个代表折线图上点的值数组:

$temperatures = [23, 24, null, '', 25, '', '', null];

我使用的是 PHP4,但我认为它可以用任何语言回答。

数组只包含数字、空值和空字符串。

数字表示温度,空值表示仪器不工作,空字符串表示两者都没有(仪器工作,只是没有测量​​任何东西)。

必须(在大多数情况下)连接点,因为它是折线图。

我有一个变量$gap,它对应于每个点,并告诉这个点是否连接到下一个点。如果设置为true,则点不连接(否则为false)。例如,temperatures[0] 的 $gap 必须设置为 false,因为在 temperatures[0] 和 temperature[1](they are both valid temperatures). $gap fortemperatures[1]andtemperatures[2] 之间绘制的线必须为真,因为有空跟随。以此类推。

当有 null 时,$gap 绝对是true。对于数字和空字符串,它取决于:如果后面是 null,则 gap 为 true;如果后面跟着一个数字,gap 是假的。如果后面是空字符串,我们必须检查后面是 null 还是 number 并相应地应用前一句。如果后面只有空字符串,则 gap 为真。这是我的代码,运行速度太慢,但产生了正确的结果:

$limit = count($temperatures);
for ($i = 0; $i <= limit; $i++) {
    $next_is_number = false;
    if (is_null($temperatures[i]) {
        $gap = true;
    } else {
        for ($y = $i + 1; $i <= limit; $i++) {
            if (is_null($temperatures[$y]) {
                break;
            } elsif (is_numeric($temperatures[$y]) {
                $next_is_number = true;
                break;
            }
        }

        if ($next_is_number) {
           $gap = false;
        } else {
           $gap = true;
        }
    }      
}

如何加快速度?

【问题讨论】:

  • 空字符串实际上代表什么?仪器在工作,但没有收集到数据?是错误还是只是缺少信息?
  • 您似乎每次都从当前位置($y = $i + 1)检查到列表末尾。您真的只想检查下一个条目是否为空白/null,而不是任何条目为空白或 null?
  • 我认为您不需要嵌套循环的第二个 forLoop。只需删除具有第二个循环的行及其各自的结束“}”并删除具有“break;”的那两行。并将 $y 替换为 $i+1 ,您的程序应该可以正常运行并且可能更快
  • @Ashish 很遗憾,需要循环。
  • @NigelRen 如果下一个是空白或空怎么办?

标签: php arrays performance loops line


【解决方案1】:

您的代码会检查折线图中某处是否存在间隙。

因此,一旦找到了间隙,就没有理由在外部 for 循环中继续。想象一张包含 1000 个值的图表,如果前两个值之间存在差距,则继续检查其他 998 个值是没有意义的。

因此,我建议的第一件事是在开始时设置 $gap = false 并在 $gap 为 true 时退出循环。您可以使用

1.) break(不那么优雅),

2.) 将代码提取到方法中并添加返回语句或

3.) 在 for 循环中添加条件。我不熟悉 php,但在大多数语言中都可以这样做:

     $gap = false;
     $limit = count($temperatures);
     for ($i = 0; $i <= limit && !$gap; $i++) {

     [...]

所以一旦 $gap 为真,外部的 for 循环就离开了。

【讨论】:

  • 我希望就这么简单!我应该写到 $gap 必须为数组的每个点/元素设置。我的代码检查每两点之间是否有间隙。
【解决方案2】:

向后迭代,记住最后一个有效值并在看到空字符串时将其放入。然后是 O(n) 最坏的情况,而不是 O(n^2)。

或者,您可以在内循环之后从$y - 1 工作到$x(反之亦然),设置间隙数组的值/输出值,然后跳过刚刚完成的所有值(@ 987654323@)。这也是 O(n)。

然后,一旦你尽可能快地掌握了算法,你就可以抛弃 PHP 并用 Rust 或 C 之类的东西编写它。(我不记得该语言中有任何真正的数组,所以它们总是会很慢。)

【讨论】:

  • 感谢您的回复!我花了一段时间才明白你的意思,但现在我认为它是完美的。请问,如果你不介意的话,你是怎么来的?有没有办法(除了更多的练习)来了解这些算法?再次非常感谢!
  • @Mandy 主要是练习。具体来说,我注意到您正在计算几个值只是为了将它们丢弃,因此我想出了一种可以存储它们的方法。
猜你喜欢
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-15
  • 1970-01-01
  • 2019-07-25
  • 1970-01-01
相关资源
最近更新 更多