0
function example()
{

    foreach ($choices as $key => $choice) {       # \__ both should run parallel
    foreach ($vtitles as $keystwo => $vtitle) {   # /

        $options .= '<option value="'. check_plain($key) .'" title="' . $vtitle . '"' . $selected  
.'>'. check_plain($choice) .'</option>';


    } // end of vtitle    
    } // end of choice

    return $options;
}

Answers to some of the below questions and what I am trying to achieve.

  1. Array $choices is not numerically indexed.
  2. Array $vtitle is numerically indexed.
  3. They won't be shorter than each other as I have code which will take care of this before this code runs.
  4. I am trying to return $options variable. The issue is that $choices[0] and $vtitle[0] should be used only once. Hope I was able to express my problem.
  5. I do not want to go through the $vtitles array once for each value in $choices.

@hakre: thanks I have nearly solved it with your help.

I am getting an error for variable $vtitle:

InvalidArgumentException: Passed variable is not an array or object, using empty array    
instead in ArrayIterator->__construct() (line 35 of /home/vishal/Dropbox/sites/chatter/sites
/all/themes/kt_vusers/template.php).

I am sure its an array this is the output using print_r

Array ( [0] => vishalkh [1] => newandold ) 

What might be going wrong ?

The below worked for me , thank you hakre

while
(
(list($key1, $value1) = each($array1))
&& (list($key2, $value2) = each($array2))
)
{
printf("%s => %s, %s => %s \n", $key1, $value1, $key2, $value2);
}
hakre
  • 193,403
  • 52
  • 435
  • 836
Vishal Khialani
  • 2,557
  • 6
  • 38
  • 49

7 Answers7

11

It does not work the way you outline with your pseudo code. However, the SPL offers a way to iterate multiple iterators at once. It's called MultipleIterator and you can attach as many iterators as you like:

$multi = new MultipleIterator();
$multi->attachIterator(new ArrayIterator($array1));
$multi->attachIterator(new ArrayIterator($array2));

foreach($multi as $value)
{
    list($key1, $key2) = $multi->key();
    list($value1, $value2) = $value;
}

See it in action: Demo

Edit: The first example shows a suggestion from the SPL. It has the benefit that it can deal with any kind of iterators, not only arrays. If you want to express something similar with arrays, you can achieve something similar with the classic while(list()=each()) loop, which allows more expressions than foreach.

while
(
    (list($key1, $value1) = each($array1))
    && (list($key2, $value2) = each($array2))
)
{
    printf("%s => %s, %s => %s \n", $key1, $value1, $key2, $value2);
}

Demo (the minimum number of elements are iterated)


See as well a related question: Multiple index variables in PHP foreach loop

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • 2
    I was not aware of this... interesting. – James Adam Feb 15 '12 at 19:18
  • What if the arrays aren't the same size? Would one key be null while the other has a value? – crush Feb 15 '12 at 19:29
  • @crush: The default behaviour is that it will only iterate over valid pairs, e.g. if one array has two members, and the other has 10, it would only iterate over the first two pairs. But you can change that with flags, see the link to the PHP manual. - [`MultipleIterator::MIT_NEED_ANY` Demo](http://codepad.viper-7.com/VYfbBw) (Yes, `NULL`). – hakre Feb 15 '12 at 19:32
  • Awesome. That's +1 worthy. Now the question is the overhead worth it haha. – crush Feb 15 '12 at 19:35
  • @hakre I am using ur suggestion with spl but I am getting a error . I have updated my post with the error. What might be going wrong ? , thanks – Vishal Khialani Feb 15 '12 at 20:03
  • @vishal: To better say what's going wrong you need to post more of your new code. Basically the error message means that the variable passed to the constructor is wrong but your print_r says it's an array which would be fine. So it's hard to say from the information given. Showing more code might reveal the culprit. You can put it on codepad viper as well where I posted the working demos, it's nice for testing smaller chunks of code. – hakre Feb 15 '12 at 20:12
2

you can't do it in foreach loop in general case. But you can do it like this in PHP5:

$obj1 = new ArrayObject($arr1);
$it1 = $obj1->getIterator();

$obj2 = new ArrayObject($arr2);
$it2 = $obj2->getIterator();

while( $it1->valid() && $it2->valid())
{
    echo $it1->key() . "=" . $it1->current() . "\n";
    $it1->next();

    echo $it2->key() . "=" . $it2->current() . "\n";
    $it2->next();    
}

In older versions of PHP it will be like this:

while (($choice = current($choices)) && ($vtitle = current($vtitles))) {       
    $key_choice = key($choices);
    $key_vtitle = key($vtitles);
    next($choices);
    next($vtitles);
}
alex347
  • 621
  • 7
  • 18
  • this would only work if both arrays had the same number of elements wouldn't it? – crush Feb 15 '12 at 19:28
  • it depends on what the author wants – alex347 Feb 15 '12 at 19:39
  • @alex347: I somewhat went into the same direction in [my answer](http://stackoverflow.com/a/9299764/367456): First an example based on iterators, and then a second one based on `while`. – hakre Feb 15 '12 at 20:03
1

Short Answer, no.

What you can do instead is:

foreach ($array1 as $k => $v)
    performMyLogic($k, $v);

foreach ($array2 as $k => $v)
    performMyLogic($k, $v);
crush
  • 16,713
  • 9
  • 59
  • 100
0

You may have to refigure your logic to do what you want. Any reason you can't just use 2 foreach loops? Or nest one inside the other?

EDIT: as others have pointed out, if PHP did support what you're trying to do, it wouldn't be safe at all.. so it's probably a good thing that it doesn't :)

James Adam
  • 2,324
  • 3
  • 16
  • 19
0

If the keys are the same, you can do this:

foreach ($choices as $key => $choice) {
    $vtitle = $vtitles[$key];
}
gen_Eric
  • 223,194
  • 41
  • 299
  • 337
0

Maybe you want this:

//get theirs keys
$keys_choices = array_keys($choices);
$keys_vtitles = array_keys($vtitles);

//the same size I guess
if (count($keys_choices) === count($keys_vtitles)) {

    for ($i = 0;$i < count($keys_choices); $i++) {

        //First array
        $key_1 = $keys_choices[$i];
        $value_1 = $choices[$keys_choices[$i]];

        //second_array
        $key_2 = $key_vtitles[$i];
        $value_2 = $vtitles[$keys_vtitles[$i]];

        //and you can operate
    }
}

But this will work if size is the same. But you can change this code.

Radek
  • 670
  • 7
  • 16
-1

You need to use two foreach loops.

foreach ($choices as $keyChoice => $choice)
{
    foreach ($vtitles as $keyVtitle => $vtitle)
    {
        //Code to work on values here
    }
}
CLo
  • 3,650
  • 3
  • 26
  • 44
  • True, I guess the question is really what is the intent of the example code? – CLo Feb 15 '12 at 19:15
  • I tried this earlier but I can't use this. As I have code inside which goes wrong then. Is there some other way ? – Vishal Khialani Feb 15 '12 at 19:17
  • @vishal Check my comment on the question itself and edit the question to clarify and we can give you a better answer. We need to know what you are trying to accomplish with the for each loop. – CLo Feb 15 '12 at 19:18