查询foreach内部是否可以?

时间:2017-10-18 15:17:48

标签: php loops foreach iteration

我在Stack / Google中搜索了很多,并没有找到我问题的正确答案,所以我在这里:

我知道使用一些计算和内容是完全不好的做法,如:

for ($i = 0; $i < count($items); $i++) 

最近我在代码中看到了一个奇怪的做法:

foreach (SomeModel::find() as $item)

将查找直接放在foreach中可以,比如count($ items)或者某种类型的?我不喜欢这个想法,所以我本能地避免放入一些var,但现在我的任务是改进/审查代码,我想结束我对此的无知,有人可以澄清我是否&# 39;是否可以接受实施?为什么?

我知道foreach是一个智能实现,只是不知道这个结构是否进行了那种优化。

2 个答案:

答案 0 :(得分:2)

如果您有for循环,则会在每次迭代中检查条件。因此,不是仅仅将var与值进行比较,而是必须在每次迭代中调用一个函数(count)。因此,在循环之前移动计数条件会产生差异

$count = count($items);
for ($i = 0; $i < $count; ++$i) { ... }

foreach表现不同。不是在每次迭代中评估SomeModel::find(),而是仅对此部分进行一次评估并仅为循环保存。您还可以将SomeModel::find()的结果保存在var中,并将该变量用于foreach循环,但这没有什么区别。如果对循环使用var only ,则编译器应该完全相同。

但请记住。如果只进行一些迭代,那种优化应该是编译器的一部分,并且时序优势应接近0。

答案 1 :(得分:1)

for()相反,每次迭代都会评估每条指令,foreach()在开头获取array,然后移动指针迭代它:

  

第一个表单循环遍历array_expression给出的数组。在每次迭代中,当前元素的值被赋值为$ value,内部数组指针被提前一个(因此在下一次迭代中,您将查看下一个元素)

强调我的

所以你的函数只被调用一次。你可以看到这种行为,看看操作码。

Without assignment

<?php
function find() {
    return [1, 2, 3, 4, 5, 6, 7, 8];
}

foreach (find() as $n) {
    echo $n.PHP_EOL;
}

操作码:

line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   3     0  E >   NOP                                                      
   7     1        INIT_FCALL                                               'find'
         2        DO_FCALL                                      0  $1      
         3      > FE_RESET_R                                       $2      $1, ->8
         4    > > FE_FETCH_R                                               $2, !0, ->8
   8     5    >   CONCAT                                           ~3      !0, '%0A'
         6        ECHO                                                     ~3
         7      > JMP                                                      ->4
         8    >   FE_FREE                                                  $2
   9     9      > RETURN                                                   1

with assignment

<?php
function find() {
    return [1, 2, 3, 4, 5, 6, 7, 8];
}
$f = find();
foreach ($f as $n) {
    echo $n.PHP_EOL;
}

操作码:

line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   3     0  E >   NOP                                                      
   6     1        INIT_FCALL                                               'find'
         2        DO_FCALL                                      0  $2      
         3        ASSIGN                                                   !0, $2
   7     4      > FE_RESET_R                                       $4      !0, ->9
         5    > > FE_FETCH_R                                               $4, !1, ->9
   8     6    >   CONCAT                                           ~5      !1, '%0A'
         7        ECHO                                                     ~5
         8      > JMP                                                      ->5
         9    >   FE_FREE                                                  $4
   9    10      > RETURN                                                   1

正如您所看到的,唯一的区别是ASSIGN指令,即指定$f时的指令。

所以这主要是一个可读性问题。在我看来,在具有适当名称的变量中分配方法的返回值会更具可读性。然而,鲍勃叔叔在清洁代码中说明了相反的意见:

  

循环的控制变量通常应该在循环语句中声明,就像来自同一来源的这个可爱的小函数一样。

public int countTestCases() {
    int count= 0;
    for (Test each : tests)
        count += each.countTestCases();
    return count;
}