我在PHP中编写了几行代码来重命名数组中的重复值(带有一些灵感from here)。 基本上,我使用原始数组($ 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输出结果不正确(重复值和通知“&”在标题[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。
答案 0 :(得分:1)
只是拿你的代码
<?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 5.3.5 / win32。看起来你的“真实”代码在循环中和/或循环之后为$ header做了其他事情。
有点简化(消除$ tmp):
<?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"
}
答案 1 :(得分:-5)
应该是
foreach(&$headers as $header) { //passing by reference
&amp; headers是对数组的引用,$ header是每个成员的句柄。您可以用任何标识符替换句柄。