在foreach里查询可以吗?

问题描述:

我搜索了很多在Stack /谷歌并没有找到一个合适的回答我的问题,所以我来到这里:在foreach里查询可以吗?

我知道用了一些计算和东西完全是不好的做法,如:

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

最近我看到的代码奇怪的做法,我的工作:

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

这是确定把直接在foreach中发现,像计数($项目)或排序的?我不喜欢这个想法,所以本能地避免了放入一些变种,但现在我的任务是改进/审查代码,我想结束对此的无知,有人可以澄清我是否可以接受实现为什么?

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

+1

好吧,我不知道在这种情况下优化,但是当涉及到可读性和清晰的代码,我敢肯定,这是清洁剂只使用一个变量'$ models'容纳结果。我有兴趣知道这种代码是否有一些性能缺陷 – teeyo

相反for(),其中每个指令在每次迭代评估,foreach()得到array在开始,然后移动指针来遍历它:

第一种形式循环中给出的阵列上由array_expression。在每次迭代中,当前元素的值被分配给$值,并且内部数组指针被提前一个(所以在下一次迭代中,您将看到下一个元素)。

重点煤矿

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

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的指令。

所以这主要是一个可读性问题。在我看来,使用合适的名称将变量的返回赋值给一个变量会更具可读性。 Bob大叔,但是,国家在清洁守则相反:

for循环控制变量通常应在循环语句中声明,如从同一来源这个可爱的小功能。

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

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

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

foreach表现不同了。而不是在每次迭代中评估SomeModel::find(),这部分只评估一次并保存为循环。您还可以将SomeModel::find()的结果保存在var中,并将该var用于foreach循环,但这没有什么区别。如果你使用var 只有作为循环,编译器应该完全一样。

但请记住。如果你只有几次迭代,那么这种优化应该是编译器的一部分,时序优势应该接近于0。

+0

您的回答很好,但@ishegg解释了很好的细节,谢谢! – calexandre