仅返回键的 PHP foreach
Posted
技术标签:
【中文标题】仅返回键的 PHP foreach【英文标题】:PHP foreach that returns keys only 【发布时间】:2012-09-03 00:51:15 【问题描述】:可能没有任何意义的理论问题,但也许有一个聪明的答案。
我想遍历数组并获取它的键和它们的一些东西。我所做的一个简单的例子:
foreach($array as $key => $value)
$other_array[$key] = 'something';
现在,php Mess Detector
尖叫着$value
在此范围内未使用。因此,我在想,也许这不是访问我的array
中的keys
的最佳方式。
知道如何在不不必要地从我的array
中取出values
的情况下做到这一点吗?它是否对性能有任何重大影响......或者我只是偏执并且应该继续而不用愚蠢的问题浪费任何人的时间:)。
【问题讨论】:
这很正常。但是你可以使用这个: $keys = array_key ($array); foreach($keys as $key) $other_array[$key] = 'something'; 您可以抑制混乱探测器的警告,例如:phpmd.org/documentation/suppress-warnings.html 【参考方案1】:你可以这样做
foreach(array_keys($array) as $key)
// do your stuff
这将使 foreach 迭代一个由数组中的键组成的数组,而不是实际的数组。请注意,从性能的角度来看,它可能并不好。
【讨论】:
我相信这里的每次迭代都会调用 array_keys(),所以这可能不是最聪明的举动? 没有,我记得如果评估一次,则进入 foreach 的数组。就像 foreach(array("a", "b", "c") as $letters) 不会在每次迭代时创建一个新数组。如果这不正确,那么可以肯定,在 foreach 之前创建一个 $keys 变量...您有任何参考指向 foreach 在每次迭代中评估数组的事实吗? 据我所知,foreach() 是使用迭代器实现的,因此只调用返回数组一次的函数。然后它使用指向现有结果集的迭代器继续处理每个项目。所以 foreach(array_keys() ... 是完全安全的 @inquam 感谢您的洞察力!这来自我的 javascript 经验,在每次迭代中执行for (var i = 0; i < abc.indexOf('aa'); i++)
会调用 indexOf。我想我的想法是所有语言都会以同样的方式做到这一点 - 我很高兴他们没有!
我做了一些测试,foreach(array_keys($arr) as $key)
比foreach($arr as $key => $val)
慢了大约 50% 到 60%。但这是正确的,你把array_keys($arr)
放在哪里没有区别。 (使用 php 5.6.0 测试了一个包含 255 个元素和 100000 轮的数组)【参考方案2】:
请忽略此消息。
在 PHP 中,您使用 foreach
的方式是最快的。正确的是,您应该避免使用未使用的变量,但在这种情况下,您无法避免它,而不会损失一些性能。
例如foreach(array_keys($arr) as $key)
大约慢 50% 到 60%
比foreach($arr as $key => $notUsed)
.
这个问题的phpmd已经上报here,也已经有pull request了here。
在phpmd更新之前你也可以使用this little hack
在 collectVariables(..)
方法中的文件 /src/main/php/PHPMD/Rule/UnusedLocalVariable.php
中(在我的例子中是第 123 行)替换
if ($this->isLocal($variable))
通过
if ($this->isLocal($variable) && !($this->isChildOf($variable, 'ForeachStatement') && $variable->getName() === '$notUsed'))
这将阻止 phpmd 在 foreach 循环内报告 $notUsed
anywhere。
更新:
上面的建议假设 PHP 5.6(撰写此答案时的相关版本)。但是时间过去了,现在使用 PHP 7.2 似乎正好相反。与往常一样,这取决于具体的用例,但对于少于 100.000 个键的关联数组,将 array_keys($arr)
存储在变量中并在 foreach 循环中使用它会更快。
【讨论】:
【参考方案3】:这是有效的 PHP 代码,不要修复代码,而是修复 PHP MD。 PHP MD 2.2 中有一个配置 并且需要这条规则:
<properties>
<property
name="allow-unused-foreach-variables"
description="Allow unused variables in foreach language constructs."
value="false" />
</properties>
【讨论】:
呃,这些行放在哪里?? @OlleHärstedt 在您正在使用的配置文件中,例如 ruleset.xml,然后是phpmd codebase/ some_output_format rulesets.xml
下面有一个提供上下文的答案。如果其他人想知道。【参考方案4】:
18C 破解 :-)
在构造as $key=>$value
中,$value首先在PHP中分配,然后再分配$key。
$array=[1,3,6,10];
foreach($array as $k => $k)
print($k.'<br/>');
对于您的代码:
foreach($array as $key => $key)
$other_array[$key] = 'something';
顺便说一句。不要使用:foreach($array as $k => &$k)
。它可能会破坏您的阵列。
【讨论】:
你依赖于内部行为。这可能会结束。 @finder2 我同意。他们可以在未来的版本中更改此行为,并且该错误将难以跟踪。我会考虑foreach ($array as $key => $_)
【参考方案5】:
如果您想将所有键设置为某个值,您可以这样做:
$array = array(
'foo'=> 'oldval1',
'bar'=> 'oldval2',
'baz'=> 'oldval3'
);
$other_array = array_fill_keys(array_keys($array), 'something');
print_r($other_array);
这将产生:
Array
(
[foo] => something
[bar] => something
[baz] => something
)
【讨论】:
+1 的想法虽然这不是我的想法 - 示例过于简单:)。无论如何谢谢 - 学习新东西:)【参考方案6】:如果您使用的是 XML 规则集:
<rule ref="rulesets/unusedcode.xml/UnusedLocalVariable">
<properties>
<property name="allow-unused-foreach-variables" value="true" />
</properties>
</rule>
【讨论】:
【参考方案7】:循环以避免 foreach 在一段时间内。
$a = ['1','A','B','12','ui'];
while(true) sleep(1);
$b = next($a) ? current($a): reset($a);
echo key($a) , ':' , $b , PHP_EOL;
【讨论】:
while(3)
更短。 :-) 此外,您应该避免潜在的无限循环。以上是关于仅返回键的 PHP foreach的主要内容,如果未能解决你的问题,请参考以下文章