2

Some Background

I have 2 arrays with the following information:

$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']
]

and

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

The goal is to place each of the elements in $x into $y with only one VIP member. I have a method to place the VIP members and then one to place everyone else. The information in $x is obtained from a database. The '1' in VIP means true.

The Problem

The problem I am having is outlined in the comments in the code below.

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;
            }
        }
    }
}

So the problem is, as you can see from the comments, when I perform if(!($y[$z['ykey']]['hasVIPmember'])){...} I only see the elements with the name "Fred" and, consequently, Fred is placed in both A and B.

The Question

Why is the list of items that are iterated through narrowed further in the final if statement? Is there any way to correct this behavior?

2
  • well, you never change hasVIPmember inside the loop, so even after you add a vipmember, you'll just keep adding more vip members,b ecause you never reset the flag to say one was added previously. Commented Sep 4, 2015 at 18:40
  • @MarcB Thanks for pointing that out. I actually do have that in my original code. I just missed it when I moved it here. Commented Sep 4, 2015 at 18:44

2 Answers 2

4

When you run the iteration Fred is first for both ranks 1 and 2. As it runs, it adds Fred to $y and then skips over the rest because at that point $y[hasVIPmember] is true. You would need to find a way to invalidate Fred from the running after he is added to any $y by using some kind of counter or key, or change your data set.

$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
                }

            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the fast answer! if( ... $z['rank'] == $i){...} prevents that from happening. I am seeing the following at the second comment (after the first if statement): When $i = 1 I see the first entry for Fred and then the first entry for Joe. When $i = 2 I see the second entry for Fred and then the second entry for Joe.
After rereading your answer, I found that you were correct. Thanks so much for your help!
2

Reason for the unexpected behavior is that you are using

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

This lead to set hasVIPmember = true for all names in $x that has ykey='A' in the first iteration.Therefore after fred has been entered joe is skipped.

Similarly it sets hasVIPmember = true for all names in $x that has ykey='B' in the second iteration.

Even if you had more names in $x they all would have been excluded.

This code gives the desirable output ,

<?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

2 Comments

I need to have only 1 VIP member in A and 1 VIP member in B. That is why I have that flag there, otherwise I will get multiples in each.
That's correct. I failed to say that order was important in my question. Sorry about that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.