使用按引用传递的 Foreach 给出的结果与按值传递不同
我在 PHP 中编写了几行代码来重命名数组中的重复值(有一些灵感 从这里)。 基本上,我遍历原始数组 ($headers[]),同时使用另一个数组 ($header_test[]) 的键来跟踪重复项。如果存在重复项,我会更改 $headers[] 中该元素的值。
但奇怪的是,我没有通过在 foreach 中传递引用来获得正确的结果。我必须使用完整的 $array_name[$key] = $new_value 格式来实际设置值。这是为什么?
(剧透警报:VolkerK 的答案是正确的 - 需要取消设置 $header (foreach“$value”变量)然后它就可以工作。)
这里:
使用此输入:
$headers = array('Abc 123 ghi',
'dangdarn',
'oops32',
'poss dup',
'poss dup',
'pos _s_ dup',
'bad chars\'& 3% 9'
);
然后应用这个自定义函数,我认为这不会影响问题手头的:
function mysql_clean_string($string) {
//remove non alnum characters
$string = preg_replace("/[^a-zA-Z0-9\s]/", "_", $string);
// replace 1+ spaces or 1+ '_' with a single '_'
$string = preg_replace("/[ _]+/", "_", $string);
$string = trim($string,'_');
if(strlen($string) > 20) {
$string = substr_replace($string,'',strpos($string,'_',20));
}
$string = strtolower($string);
return $string;
}
array_walk($headers,'mysql_clean_string'); // limit headers to alnum chars
通过引用传递数组值无法正常工作(请参阅下面的 var_dump()):
$header_test = array();
foreach($headers as &$header) { //passing by reference
$temp = $header;
if(array_key_exists($temp,$header_test)) {
**$header = $header . '_' . $header_test[$header];**
$header_test[$temp]++;
unset($temp);
} else {
$header_test[$temp] = 1;
}
}
//here is the solution VolkerK suggested and it works:
unset($header);
以下是 var_dump 输出,其结果不正确(重复值并注意 headers[6] 处的“&”,并且缺少最后一个值):
["headers"]=>
array(7) {
[0]=>
string(11) "abc_123_ghi"
[1]=>
string(8) "dangdarn"
[2]=>
string(6) "oops32"
[3]=>
**string(8) "poss_dup"**
[4]=>
string(10) "poss_dup_1"
[5]=>
string(9) "pos_s_dup"
[6]=>
**&string(8) "poss_dup"**
}
["header_test"]=>
array(6) {
["abc_123_ghi"]=>
int(1)
["dangdarn"]=>
int(1)
["oops32"]=>
int(1)
["poss_dup"]=>
int(2)
["pos_s_dup"]=>
int(1)
["bad_chars_3_9"]=>
int(1)
}
现在这是可行的,即使用 $original_array[$key] = $new_value 格式:
$header_test = array();
foreach($headers as $key => $header) {
$temp = $header;
if(array_key_exists($temp,$header_test)) {
**$headers[$key] = $header . '_' . $header_test[$header];**
$header_test[$temp]++;
unset($temp);
} else {
$header_test[$temp] = 1;
}
}
var_dump:
["headers"]=>
array(7) {
[0]=>
string(11) "abc_123_ghi"
[1]=>
string(8) "dangdarn"
[2]=>
string(6) "oops32"
**[3]=>
string(8) "poss_dup"
[4]=>
string(10) "poss_dup_1"**
[5]=>
string(9) "pos_s_dup"
**[6]=>
string(13) "bad_chars_3_9"**
}
["header_test"]=>
array(6) {
["abc_123_ghi"]=>
int(1)
["dangdarn"]=>
int(1)
["oops32"]=>
int(1)
["poss_dup"]=>
int(2)
["pos_s_dup"]=>
int(1)
["bad_chars_3_9"]=>
int(1)
}
VolkerK 提出了解决方案。除了他的其他好的建议之外,关键是在 foreach 循环之后取消设置 $header 。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的代码即可
生成
只需使用 php 5.3.5/win32 在我的机器上 。看起来您的“真实”代码在循环中和/或循环后对 $header 执行了其他操作。
有点简化(消除 $tmp):
打印
just taking your code
produces
on my machine using php 5.3.5/win32. Looks like your "real" code does something else to $header in and/or after the loop.
A bit simplified (eliminating $tmp):
prints
应该是
&headers 是对数组的引用,$header 是每个成员的句柄。您可以用任何标识符替换句柄。
It should be
&headers is the reference to the array and $header is a handle for each member. You could replace the handle with any identifier.