在foreach里查询可以吗?
我搜索了很多在Stack /谷歌并没有找到一个合适的回答我的问题,所以我来到这里:在foreach里查询可以吗?
我知道用了一些计算和东西完全是不好的做法,如:
for ($i = 0; $i < count($items); $i++)
最近我看到的代码奇怪的做法,我的工作:
foreach (SomeModel::find() as $item)
这是确定把直接在foreach中发现,像计数($项目)或排序的?我不喜欢这个想法,所以本能地避免了放入一些变种,但现在我的任务是改进/审查代码,我想结束对此的无知,有人可以澄清我是否可以接受实现为什么?
我知道foreach是一个智能实现,只是不知道这个结构是否做这种优化。
相反for()
,其中每个指令在每次迭代评估,foreach()
得到array
在开始,然后移动指针来遍历它:
第一种形式循环中给出的阵列上由array_expression。在每次迭代中,当前元素的值被分配给$值,并且内部数组指针被提前一个(所以在下一次迭代中,您将看到下一个元素)。
重点煤矿
所以你的函数被调用一次。你可以看到这个行为看着操作码。
<?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
<?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。
您的回答很好,但@ishegg解释了很好的细节,谢谢! – calexandre
好吧,我不知道在这种情况下优化,但是当涉及到可读性和清晰的代码,我敢肯定,这是清洁剂只使用一个变量'$ models'容纳结果。我有兴趣知道这种代码是否有一些性能缺陷 – teeyo