Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 带有传递引用的Foreach给出的结果与传递值不同_Php_Foreach_Pass By Reference - Fatal编程技术网

Php 带有传递引用的Foreach给出的结果与传递值不同

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”

我用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"
}