简体   繁体   English

如何使循环更快?

[英]How can I make a loop faster?

I have an array of values that represent points on a line chart: 我有一个代表折线图上点的值数组:

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

I'm using PHP4, but I think it can be answered in any language. 我正在使用PHP4,但是我认为可以用任何语言回答。

Array contains only numbers, nulls and empty strings. 数组仅包含数字,空值和空字符串。

Numbers represent temperatures, nulls mean that the instruments weren't working and empty strings represent neither (instruments are working, just not measuring anything). 数字代表温度,空值代表仪器不工作,空字符串代表两者都不工作(仪器正在工作,只是没有测量​​任何东西)。

Points must (in most cases) be connected, since it's a line chart. 由于是折线图,因此必须(在大多数情况下)连接点。

I have a variable $gap that corresponds to each point and tells whether this point is connected to the next point. 我有一个变量$gap ,它对应于每个点,并告诉该点是否连接到下一个点。 If it is set to true , than the points are not connected ( false otherwise). 如果将其设置为true ,则不连接这些点(否则为false )。 For example, $gap for temperatures[0] must be set to false , since the line is drawn between temperatures[0] and temperatures[1] (they are both valid temperatures). $gap for 例如, temperatures[0] $ gap必须设置为false ,因为这条线是在temperatures[0]和温度[1]之间绘制的(they are both valid temperatures). $gap for (they are both valid temperatures). $gap for temperatures[1] and temperatures[2]` must be true, since there is null following. 温度[1] and温度[2]`的(they are both valid temperatures). $gap for必须为true,因为后面没有空。 And so on. 等等。

When there is null the $gap is absolutely true . 当为null时,$ gap绝对为true For numbers and empty strings, it depends on: if a null follows, gap is true; 对于数字和空字符串,取决于:如果后面为null,则差为true;否则为false。 if a number follows, gap is false. 如果后面跟随数字,则差值为假。 If empty string follows, we must check if afterwards comes null or number and apply the previous sentence accordingly. 如果后面跟着空字符串,则必须检查之后是否为空或数字,并相应地应用前面的句子。 If there are just empty strings following, gap is true. 如果紧随其后的是空字符串,则gap为true。 Here is my code that is working too slow, but produce correct results: 这是我的代码,运行速度太慢,但是产生正确的结果:

$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;
        }
    }      
}

How can I speed it up? 我如何加快速度?

Your code checks whether there is aa gap somewhere in your line chart or not. 您的代码将检查折线图中某处是否存在缺口。

So once a gap is found, there no reason to continue in the outer for-loop. 因此,一旦发现差距,就没有理由继续在外部for循环中了。 Think of a chart of 1000 values, if there is a gap between the first two values it makes no sense to continue checking the other 998 values. 试想一下一个包含1000个值的图表,如果前两个值之间存在间隙,则继续检查其他998个值是没有意义的。

Thus, the first thing I would recommend is to set $gap = false at the beginning and to leave the loop once $gap is true. 因此,我建议的第一件事是在开始时设置$ gap = false,并在$ gap为true时退出循环。 You could do that either with 你可以用

1.) break (not so elegant), 1.)休息(不是那么优雅),

2.) extract your code to a method and add a return-statement or 2.)将您的代码提取到方法中,并添加一个返回语句或

3.) adding a condition in the for-loop. 3.)在for循环中添加条件。 I am not familiar with php but in most languages it is possible to do it like this: 我不熟悉php,但在大多数语言中都可以这样进行:

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

     [...]

So once $gap is true, the outer for-loop is left. 因此,一旦$ gap为真,则将保留外部for循环。

Iterate through backwards, remembering the last valid value and putting that in when you see an empty string. 向后迭代,记住最后一个有效值,并在看到空字符串时将其放入。 Then it's O(n) worst case, not O(n^2). 那么这是O(n)最坏的情况,而不是O(n ^ 2)。

Alternatively, you can work from $y - 1 to $x (or vice versa) after the inner loop, setting the values of your gaps array / outputting values, then skip past all the ones you've just done ( $x = $y ). 或者,您可以在内循环之后从$y - 1$x (反之亦然)工作,设置间隙数组的值/输出值,然后跳过所有刚刚完成的操作( $x = $y )。 This is also O(n). 这也是O(n)。

Then, once you've got the algorithm as fast as you can, you can ditch PHP and write it in something like Rust or C. (I don't recall any true arrays in the language, so they're always going to be slow.) 然后,一旦您尽可能快地获得算法,就可以抛弃PHP并以Rust或C之类的语言编写它。(我不记得该语言中的任何真实数组,因此它们总是慢。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM