在foreach循环参数中展开一个数组

编程入门 行业动态 更新时间:2024-10-27 15:27:36
本文介绍了在foreach循环参数中展开一个数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

foreach(explode(','$ foo)as $ bar){...}

$ test = explode(','$ foo); foreach($ test as $ bar){...}

在第一个例子,是否为每次迭代爆炸 $ $ foo 字符串还是PHP保存在内存中爆炸在它自己的临时变量?从效率的角度来看,创建额外变量 $ test 还是几乎相等?

解决方案

我可以做一个有根据的猜测,但是我们试试看吧!

有三种主要方法可以解决这个问题。 $ b $ ol <

  • 在进入循环之前进行爆炸和分配
  • 爆炸在循环中,没有赋值
  • 字符串标记大小
  • 我的假设:

  • 由于赋值而可能消耗更多的内存
  • 可能与#1或#3相同,不知道哪个
  • 可能会更快,更小的内存占用
  • 方法 $ p $ b $ ini_set('memory_limit ','1024M'); $ listStr ='text'; $ listStr。= str_repeat(',text',9999999); $ timeStart = microtime(true); / ***** * {INSERT LOOP HERE} * / $ timeEnd = microtime(true); $ timeElapsed = $ timeEnd - $ timeStart; $ b printf(Memory used:%s kB\\\,memory_get_peak_usage()/ 1024); printf(Total time:%s s \\\,$ timeElapsed);

    以下是三个版本:

    1)

    //分别爆炸 $ arr = explode(',',$ listStr); foreach($ arr as $ val){}

    //展开内联 foreach(explode(',',$ listStr)as $ val){} // tokenize $ tok = strtok($ listStr,','); while($ tok = strtok(',')){}

    h2>

    结论

    看起来有些假设是错误的。你不喜欢科学吗? : - )

    • 总的来说,任何这些方法对于合理大小如果你正在遍历巨大的,时间差异相对较小,但是内存使用可能会有一个数量级的差异!
    • >
    • 当您的 explode()没有预先赋值时,它会慢一些。
    • <令人惊讶的是,标记化比显式迭代声明的数组慢了一点。在这么小的范围内工作,我认为这是由于每次迭代调用函数 strtok()的调用堆栈开销。

    根据函数调用的数量, explode()

    )在循环中调用一个函数。我用 strlen($ val),认为这会是一个相对相似的执行时间。这是有争议的,但我只是想说明一个问题。 (我只运行了 strlen($ val)并忽略了输出,我没有把它分配给任何东西,因为赋值是一个额外的时间) $ $ p $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ foreach($ arr as $ val){strlen($ val);}

    你可以从结果表中看到,然后成为三者中最慢的方法。 最后的想法

    这是很有趣的知道,但我的建议是做任何你觉得最可读/可维护。只有当你真的处理一个非常大的数据集时,你应该担心这些微观优化问题。

    foreach(explode(',' $foo) as $bar) { ... }

    vs

    $test = explode(',' $foo); foreach($test as $bar) { ... }

    In the first example, does it explode the $foo string for each iteration or does PHP keep it in memory exploded in its own temporary variable? From an efficiency point of view, does it make sense to create the extra variable $test or are both pretty much equal?

    解决方案

    I could make an educated guess, but let's try it out!

    I figured there were three main ways to approach this.

  • explode and assign before entering the loop
  • explode within the loop, no assignment
  • string tokenize
  • My hypotheses:

  • probably consume more memory due to assignment
  • probably identical to #1 or #3, not sure which
  • probably both quicker and much smaller memory footprint
  • Approach

    Here's my test script:

    <?php ini_set('memory_limit', '1024M'); $listStr = 'text'; $listStr .= str_repeat(',text', 9999999); $timeStart = microtime(true); /***** * {INSERT LOOP HERE} */ $timeEnd = microtime(true); $timeElapsed = $timeEnd - $timeStart; printf("Memory used: %s kB\n", memory_get_peak_usage()/1024); printf("Total time: %s s\n", $timeElapsed);

    And here are the three versions:

    1)

    // explode separately $arr = explode(',', $listStr); foreach ($arr as $val) {}

    2)

    // explode inline-ly foreach (explode(',', $listStr) as $val) {}

    3)

    // tokenize $tok = strtok($listStr, ','); while ($tok = strtok(',')) {}

    Results

    Conclusions

    Looks like some assumptions were disproven. Don't you love science? :-)

    • In the big picture, any of these methods is sufficiently fast for a list of "reasonable size" (few hundred or few thousand).
    • If you're iterating over something huge, time difference is relatively minor but memory usage could be different by an order of magnitude!
    • When you explode() inline without pre-assignment, it's a fair bit slower for some reason.
    • Surprisingly, tokenizing is a bit slower than explicitly iterating a declared array. Working on such a small scale, I believe that's due to the call stack overhead of making a function call to strtok() every iteration. More on this below.

    In terms of number of function calls, explode()ing really tops tokenizing. O(1) vs O(n)

    I added a bonus to the chart where I run method 1) with a function call in the loop. I used strlen($val), thinking it would be a relatively similar execution time. That's subject to debate, but I was only trying to make a general point. (I only ran strlen($val) and ignored its output. I did not assign it to anything, for an assignment would be an additional time-cost.)

    // explode separately $arr = explode(',', $listStr); foreach ($arr as $val) {strlen($val);}

    As you can see from the results table, it then becomes the slowest method of the three.

    Final thought

    This is interesting to know, but my suggestion is to do whatever you feel is most readable/maintainable. Only if you're really dealing with a significantly large dataset should you be worried about these micro-optimizations.

    更多推荐

    在foreach循环参数中展开一个数组

    本文发布于:2023-11-26 12:25:00,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1633924.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:数组   参数   foreach

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!