Join 2 arrays together There are 2 arrays. One that consists of Categories and one of Products. Each product pertains to its specific category. I want to join each product to its right category (a category can have multiple products). Each product that 'finds' its category will go in this category's products array.

for ($i = 0; $i &lt; count($prods); $i++)
{
    for ($u = 0; $u &lt; count($cats); $u++)
    {
        if ($prods[$i]['category_code'] === $cats[$u]['category_style_code'])
        {
            if ( !isset($cats[$u]['products']) )
            {
                $cats[$u]['products'] = array();
            }
            array_push($cats[$u]['products'], $prods[$i]);
        }
    }
}


It results in something like:

Array
(
    [0] =&gt; Array
        (
            [id] =&gt; 1
            [category_style_code] =&gt; GA
            [products] =&gt; Array
                (
                    [0] =&gt; Array
                        (
                            [id] =&gt; 1
                            [default_price] =&gt; 37.50
                            [category_code] =&gt; GA
                        )

                    [1] =&gt; Array
                        (
                            [id] =&gt; 2
                            [default_price] =&gt; 15.00
                            [category_code] =&gt; GA
                        )
                )
        )
)


Let's say there are many categories and many products. How would you optimize this code (or do it differently)?
Tweaks


for ($i = 0; $i &lt; count($prods); $i++)
{
    for ($u = 0; $u &lt; count($cats); $u++)
    {



I'd avoid calling count on each iteration of the loop.  Save the value at initialization time instead.  

for ( $i = 0, $n = count($prods); $i &lt; $n; $i++ ) {
    for ( $u = 0, $m = count($cats); $u &lt; $m; $u++ ) {


I'd flip these around.  

foreach ( $cats as &amp;$category ) {
    foreach ( $prods as $product ) {


The switch to foreach means that you aren't having to muck with the count.  It will handle that in the background.  


            array_push($cats[$u]['products'], $prods[$i]);



When adding a single value, []= is more efficient than array_push.  

            $category['products'][] = $product;


When you use the reference version of foreach, you should explicitly break the reference using unset when done.  

unset($category);


Note that if $cats were the inner loop, we'd need to do this for every iteration of the outer loop.  

So in whole, that gives us 

foreach ( $cats as &amp;$category ) {
    foreach ( $prods as $product ) {
        if ( $product['category_code'] === $category['category_style_code'] ) {
            if ( ! isset($category['products']) ) {
                $category['products'] = array();
            }

            $category['products'][] = $product;
        }
    }
}

unset($category);


New Algorithm

But we can do even better.  Note that this runs count($cats) times count($prods) iterations.  But we don't actually have to check every category against every product.  We just need a way to look up the category for a given code.  

    $category_of = array();
    foreach ( $cats as &amp;$category ) {
        $category_of[$category['category_style_code']] = &amp;$category;
    }
    unset($category);


Now our $prods loop can just look up the category.  

    foreach ( $prods as $product ) {
        if ( isset($category_of[$product['category_code']]) ) {
            if ( ! isset($category_of[$product['category_code']]['products']) ) {
                $category_of[$product['category_code']]['products'] = array();
            }

            $category_of[$product['category_code']]['products'][] = $product;
        }
    }


If we don't mind having empty products arrays in a category, we can speed up the second loop by moving the check into the first loop.  

    $category_of = array();
    foreach ( $cats as &amp;$category ) {
        $category_of[$category['category_style_code']] = &amp;$category;

        if ( ! isset($category['products']) ) {
            $category['products'] = array();
        }
    }
    unset($category);


Now each $category['products'] is guaranteed to be set, so we only do this check once per category not once per product.  Note that we may not need to do the check.  if we know that $category['products'] is not set until we do this, we can just do the assignment.  

Currently we check that a given category exists before assigning.  If this will always be true, then we can remove the check and just assign:

    foreach ( $prods as $product ) {
        $category_of[$product['category_code']]['products'][] = $product;
    }


Now we iterate count($cats) plus count($prods) times.  This sum should be smaller than the product in most cases.  The exceptions would be single element cases (only one product or one category or both).  This will use more memory (for the $category_of array), but hopefully you aren't right up against the memory limit anyway.  

Final Version

    $category_of = array();
    foreach ( $cats as &amp;$category ) {
        $category_of[$category['category_style_code']] = &amp;$category;

        $category['products'] = array();
    }
    unset($category);

    foreach ( $prods as $product ) {
        $category_of[$product['category_code']]['products'][] = $product;
    }


Another advantage of this version is that it is the first loop that does more work.  Since there are more products than categories (because there are multiple products per category but only one category per product in this model), this should speed things up.  

Remember our assumptions though.  If they don't hold true, then the code should change:


$category['products'] is not set with data we need for any category prior to this code.
There is always a category for every $product['category_code'].  


The original code did not make these assumptions.  It's unclear if that is because they don't hold as it needed the checks for other purposes.  Additional context might have made this clearer.  

An advantage of this version is that it will throw an error if the second assumption does not hold.  The original code would just leave things in an inconsistent state.