PHP - 嵌套foreach循环中的意外行为

时间:2015-09-04 18:32:44

标签: php

一些背景

我有2个数组,其中包含以下信息:

$x = [
    ['name' => 'Fred', 'ykey' => 'A', 'rank' => '1', 'VIP' => '1'],
    ['name' => 'Fred', 'ykey' => 'B', 'rank' => '2', 'VIP' => '1'],
    ['name' => 'Joe', 'ykey' => 'A', 'rank' => '1', 'VIP' => '1'],
    ['name' => 'Joe', 'ykey' => 'B', 'rank' => '2', 'VIP' => '1'],
    ['name' => 'Frank', 'ykey' => 'A', 'rank' => '1', 'VIP' => '0'],
    ['name' => 'Frank', 'ykey' => 'B', 'rank' => '2', 'VIP' => '0']
]

$y = [
    'A' => [
        'hasVIPmember' => false,
        'slots' = [] //X elements will be placed here
    ]
    'B' => [
        'hasVIPmember' => false,
        'slots' = [] //X elements will be placed here
    ]

目标是将$x中的每个元素放入$y,只有一个VIP成员。我有一种方法可以放置VIP会员,然后放置其他人。 $x中的信息是从数据库中获取的。 VIP中的“1”表示true

问题

我遇到的问题在下面的代码中的注释中列出。

for($i = 1; $i <= 2; $i++){
    foreach($x as $z){
        //all Xs are seen here (after all iterations complete)
        if($z['VIP'] == 1 && $z['rank'] == $i){
            //Only Fred and Joe elements of X are shown here. (after all iterations complete)
            if(!($y[$z['ykey']]['hasVIPmember'])){
                //Only 'Fred' elements are shown here. Why?(after all iterations complete)
                $y[$z['ykey']]['slots'][]= $z;
                $y[$z['ykey']]['hasVIPmember'] = true;
            }
        }
    }
}

所以问题是,正如你从评论中看到的那样,当我执行if(!($y[$z['ykey']]['hasVIPmember'])){...}时,我只看到名为“Fred”的元素,因此,Fred被置于A和B中。

问题

为什么迭代的项目列表在最终的if语句中进一步缩小?有没有办法纠正这种行为?

2 个答案:

答案 0 :(得分:4)

当您运行迭代时,Fred首先用于第1和第2列。在运行时,它将Fred添加到$ y,然后跳过其余部分,因为此时$ y [hasVIPmember]为true。你需要找到一种方法,通过使用某种计数器或密钥将Fred添加到任何$ y,或更改数据集,从而使Fred无效。

$used = NULL;
for($i = 1; $i <= 2; $i++){
    foreach($x as $z){
        //all Xs are seen here (after all iterations complete)
        if($z['VIP'] == 1 && $z['rank'] == $i){
            //Only Fred and Joe elements of X are shown here. (after all iterations complete)
            if(!($y[$z['ykey']]['hasVIPmember'])){
                // looks for used
                if (!($z['name'] == $used)) {
                    $y[$z['ykey']]['slots'][]= $z;
                    $y[$z['ykey']]['hasVIPmember'] = true;
                    $used = $z['name']; //add Fred to the used name list
                }

            }
        }
    }
}

答案 1 :(得分:2)

出现意外行为的原因是您正在使用

$y[$z['ykey']]['hasVIPmember'] = true;

这导致为$ x中所有在第一次迭代中具有ykey ='A'的名称设置hasVIPmember = true。因此,在输入fred之后,跳过了joe。

类似地,它为$ x中所有在第二次迭代中具有ykey ='B'的名称设置hasVIPmember = true。

即使您在$ x中有更多名称,他们也会被排除在外。

此代码提供了理想的输出

<?php

$x = [
['name' => 'Fred', 'ykey' => 'A', 'rank' => '1', 'VIP' => '1'],
['name' => 'Joe', 'ykey' => 'A', 'rank' => '1', 'VIP' => '1'],
['name' => 'Fred', 'ykey' => 'B', 'rank' => '2', 'VIP' => '1'],
['name' => 'Joe', 'ykey' => 'B', 'rank' => '2', 'VIP' => '1'],
['name' => 'Frank', 'ykey' => 'A', 'rank' => '1', 'VIP' => '0'],
['name' => 'Frank', 'ykey' => 'B', 'rank' => '2', 'VIP' => '0']
];

$y = [
'A' => [ 'hasVIPmember' => false , 'slots' => []  ],
'B' => [ 'hasVIPmember' => false , 'slots' => []  ]

 ];


for($i = 1; $i <= 2; $i++){
foreach($x as $z){
    //all Xs are seen here (after all iterations complete)
    if($z['VIP'] == 1 && $z['rank'] == $i){
       //Only Fred and Joe elements of X are shown here. (after all iterations complete)
        if(!($y[$z['ykey']]['hasVIPmember']))
          {
          echo $z['name']; // printing to check the name 
          echo $z['ykey']; // printing to check the ykey
          echo "<br>";  
          $y[$z['ykey']]['slots'][]= $z;

    }

}

}
}

?>

enter image description here