tags:

views:

192

answers:

7

I need to combine two foreach statement into one for example

foreach ($categories_stack as $category)
foreach ($page_name as $value)

I need to add these into the same foreach statement

Is this possible if so how?

thanks

+3  A: 

You can do nested foreachs if that's what you want. But without knowing more of your data, it's impossible to say if this helps:

foreach ($categories_stack as $category) {
    foreach ($page_name as $value) {
    }
}

Probably you want to print out all pages in a category? That probably won't work, so can you give a bit more info on how the arrays look like and relate to each other?

Tatu Ulmanen
I don't think he wants them nested.
kemp
I don't either but until he provides more information, that's as good a guess as everyone else's.
Tatu Ulmanen
A: 

Could you just nest them with variables outside the scope of the foreach, or prehaps store the content as an array similar to a KVP setup? My answer is vague but I'm not really sure why you're trying to accomplish this.

Andrew Weir
A: 

Do the array elements have a direct correspondence with one another, i.e. is there an element in $page_name for each element in $categories_stack? If so, just iterate over the keys and values (assuming they have the same keys):

foreach ($categories_stack as $key => $value)
{
    $category = $value;
    $page = $page_name[$key];

    // ...
}
Will Vousden
+1  A: 

This is where the venerable for loop comes in handy:

for(
    $i = 0,
    $n = sizeof($categories_stack),
    $m = sizeof($page_name);

    $i < $n && $i < $m;

    $i++
) {
    $category = $categories_stack[$i];
    $value = $page_name[$i];

    // do stuff here ....
}
slebetman
You could make that a whole lot more readable by putting `$n = min(count($categories_stack), count($page_name))` above the loop and then just using the standard `for ($i = 0; $i < $n; $i++)` format.
Will Vousden
Personally I find putting the init part outside the `for()` to be less readable. This way the _intent_ is clear, it is to initialize variables for the `for` loop. But that's just a matter of style of course, PHP does not do scoping for `for` loops.
slebetman
@slebetman I agree with you on this one, but I tend to write it outside anyway. It's strange. :)
Peter Lindqvist
+4  A: 

(I am not sure I have understood your question completely. I am assuming that you want to iterate through the two lists in parallel)

You can do it using for loop as follows :

$n = min(count($category), count($value));
for($c = 0; $c < $n; $c = $c + 1){
    $categories_stack = $category[$c];
    $pagename = $value[$c];
    ...
}

To achieve the same with foreach you need a function similar to Python's zip() function.

In Python, it would be :

for categories_stack, pagename in zip(categories, values):
     print categories_stack, pagename

Since PHP doesn't have a standard zip() function, you'll have to write such a function on your own or go with the for loop solution.

missingfaktor
You realize that in order to write the zip function you need a foreach loop that uses the zip function ;-) Of course, there's always the for loop.
slebetman
@Rahul, this assumption would only be correct in the even the number of array items was the same for both pages and categories, which is highly unlikely.
cballou
Simple `for` is the best solution
kemp
@cballou : OP's question is not clear. I have stated it clearly that I am assuming that he wants to iterate the two lists in parallel. I don't think he wants to nest the two loops (what you seem to think from your solution.)
missingfaktor
They could be associate arrays. In that case you will have to use array_slice or another similar function.
presario
+1  A: 

Surely you can just merge the arrays before looping?

$data = array_merge($categories_stack, $page_name);

foreach($data AS $item){
...
}
adam
+1  A: 

This loop will continue to the length of the longest array and return null for where there are no matching elements in either of the arrays. Try it out!

$a = array(1 => "a",25 => "b", 10 => "c",99=>"d");
$b = array(15=>1,5=>2,6=>3);

$ao = new ArrayObject($a);
$bo = new ArrayObject($b);
$ai = $ao->getIterator();
$bi = $bo->getIterator();
for (
    $ai->rewind(),$bi->rewind(),$av = $ai->current(),$bv = $bi->current();
    list($av,$bv) =
        array(
            ($ai->valid() ? $ai->current() : null),
            ($bi->valid() ? $bi->current() : null)
        ), 
    ($ai->valid() || $bi->valid());
    ($ai->valid() ? $ai->next() : null),($bi->valid() ? $bi->next() : null))
{
    echo "\$av = $av\n";
    echo "\$bv = $bv\n";
}

I cannot really tell from the question exactly how you want to traverse the two arrays. For a nested foreach you simply write

foreach ($myArray as $k => $v) {
    foreach ($mySecondArray as $kb => $vb {
    }
}

However you can do all sorts of things with some creative use of callback functions. In this case an anonymous function returning two items from each array on each iteration. It's then easy to use the iteration value as an array or split it into variables using list() as done below.

This also has the added benefit of working regardless of key structure. I's purely based on the ordering of array elements. Just use the appropriate sorting function if the elements are out of order.

It does not worry about the length of the arrays as there is no error reported, so make sure you keep an eye out for empty values.

$a = array("a","b","c");
$b = array(1,2,3);
foreach (
        array_map(
            create_function(
                '$a,$b', 'return array($a,$b);'
            )
            ,$a,$b
        )
        as $value
    ) 
{
    list($a,$b) = $value;
    echo "\$a = $a\n";
    echo "\$b = $b\n";
}

Output

$a = a
$b = 1
$a = b
$b = 2
$a = c
$b = 3

Here's another one for you that stops on either of the lists ending. Same as using min(count(a),count(b). Useful if you have arrays of same length. If someone can make it continue to the max(count(a),count(b)) let me know.

$ao = new ArrayObject($a);
$bo = new ArrayObject($b);
$ai = $ao->getIterator();
$bi = $bo->getIterator();
for (
    $ai->rewind(),$bi->rewind();
    $av = $ai->current(),$bv=$bi->current();
    $ai->next(),$bi->next())
{
    echo "\$av = $av\n";
    echo "\$bv = $bv\n";
}
Peter Lindqvist