Php 带有传递引用的Foreach给出的结果与传递值不同
我用PHP编写了几行代码来重命名数组中的重复值(灵感来源于此)。 基本上,我遍历原始数组($headers[]),同时使用另一个数组($header_test[])的键跟踪重复的数组。如果存在重复项,我将更改$headers[]中该元素的值 但奇怪的是,我在foreach中通过引用传递没有得到正确的结果。我必须使用完整的$array\u name[$key]=$new\u值格式来设置值。为什么呢 (剧透警报:VolkerK的答案是正确的-需要取消设置$header(foreach“$value”变量),然后它就可以工作了。) 在这里: 使用此输入:Php 带有传递引用的Foreach给出的结果与传递值不同,php,foreach,pass-by-reference,Php,Foreach,Pass By Reference,我用PHP编写了几行代码来重命名数组中的重复值(灵感来源于此)。 基本上,我遍历原始数组($headers[]),同时使用另一个数组($header_test[])的键跟踪重复的数组。如果存在重复项,我将更改$headers[]中该元素的值 但奇怪的是,我在foreach中通过引用传递没有得到正确的结果。我必须使用完整的$array\u name[$key]=$new\u值格式来设置值。为什么呢 (剧透警报: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()):
以下是结果不正确的var_转储输出(重复的值和标题[6]处的“&”,以及缺少的最后一个值):
现在,使用$original_数组[$key]=$new_值格式:
$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;
}
}
变量转储:
$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);
["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)
}
沃尔克想出了解决办法。除了他的其他好建议外,关键是在foreach循环后取消$header。应该是这样的
foreach(&$headers as $header) { //passing by reference
&headers是对数组的引用,$header是每个成员的句柄。您可以用任何标识符替换句柄。只需获取代码即可
<?php
$headers = array('Abc 123 ghi',
'dangdarn',
'oops32',
'poss dup',
'poss dup',
'pos _s_ dup',
'bad chars\'& 3% 9'
);
$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;
}
}
var_dump($headers);
在我的机器上使用PHP5.3.5/win32。看起来您的“真实”代码在循环中和/或循环后对$header执行了其他操作
稍微简化(省去$tmp):
我猜你不能用粗体编码,但这正是我试图用星号做的,是的,我在那里运行了一个函数。我将把它添加到问题中,但我不认为它会影响任何事情,因为它只是使用一些正则表达式来清理字符串。是的,这是完全非法的。请参阅PHP手册。我做得很好,在$header之前放置&before,而不是$headers。谢谢,实际上看起来unset($header)已经达到了预期的效果。没有它,我就得到了前面有引用的重复值,它会立即更改为数组中正确的最后一个值。这是奇怪的行为,不是吗?我最终肯定会把它变成一个函数。还感谢您对foreach循环的良好建议。实际上,我只是为了测试这个bug引入了$temp变量。谢天谢地,我现在可以摆脱它了。谢谢
<?php
$headers = array('Abc 123 ghi',
'dangdarn',
'oops32',
'poss dup',
'poss dup',
'pos _s_ dup',
'bad chars\'& 3% 9'
);
$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;
}
}
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(12) "pos _s_ dup"
[6]=>
&string(16) "bad chars'& 3% 9"
}
<?php
$headers = getData();
$header_test = array();
foreach($headers as &$header) { //passing by reference
if( array_key_exists($header, $header_test) ) {
$header = $header . '_' . $header_test[$header]++;
}
else {
$header_test[$header] = 1;
}
}
// removes the reference that's causing the & in front
// of the last element of $headers in the output of var_dump
// if $headers can be empty you need to guard this
// to avoid "undefined variable 'header' warning.
// Probably better to put this code in a function
// so that $header can fall out of scope automagically
unset($header);
var_dump($headers);
function getData() {
return array('Abc 123 ghi',
'dangdarn',
'oops32',
'poss dup',
'poss dup',
'pos _s_ dup',
'bad chars\'& 3% 9',
'poss dup',
'poss dup'
);
}
array(9) {
[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(12) "pos _s_ dup"
[6]=>
string(16) "bad chars'& 3% 9"
[7]=>
string(10) "poss dup_2"
[8]=>
string(10) "poss dup_3"
}