views:

198

answers:

3

I have a PHP array that looks like this:

Array
(
[340] => Array
    (
        [1] => 1
        [2] => 18
        [3] => 23
    )

[341] => Array
    (
        [1] => 1
        [2] => 17
        [3] => 23
    )

[342] => Array
    (
        [1] => 1
        [2] => 16
        [3] => 23
    )

[343] => Array
)

The array is actually longer and contains about 40 elements. There will be other arrays that contain a different number of child elements. The array is formatted as

productID => array (
    $attributeID => attributeValueID,
    $attributeID => attributeValueID,
    $attributeID => attributeValueID
)

What I need is an array that shows the valid values for all other attributes. The output array might looks something like

Array
(
18 => array(
    1 => array(
        11, 12, 13, 14, 15
    )
    2 => array(
        19, 20, 21, 22
    )
)
19 => array(
    1 => array(
        11, 13, 14, 15
    )
    2 => array(
        21, 22
    )
)

The format of this array is

attributeValueID => array(
    attributeID => attributeValues,
    attributeID => attributeValues
)

I've been working with some recursion functions but I've only been able to get a list of every possible combination between all the values which isn't what I need. Any help would be greatly appreciated.

Clarification on what I mean by "valid" values: What the 1, 2, and 3 values represent here are color, size, and length. The ultimate goal here is to create a series of javascript arrays I'll use to update options on the page when a user selects values. For example when they select the color black I need to update the sizes and lengths on the page to reflect only sizes and lengths available in black. I can create the arrays manually but this is not a good solution.

A: 

Assuming the output should actually be:

attributeValueID => array(
    attributeID => productID,
    attributeID => productID
)

(If not where do the attribute values come from?)

Recursion would not be needed, just something along these lines to re-jig the array:

$products = array(   340 => array(
            1 => 1,
            2 => 18,
            3 => 23
            ),

         341 => array(
                  1 => 1,
                  2 => 17,
                  3 => 23
               ),

         342 => array(
                  1 => 1,
                  2 => 16,
                  3 => 23
               ),

         343 => array()
        );
$output = array();

foreach($products as $product_id=>$attributes){
    $attribute_id;
    foreach($attributes as $attribute_id=>$attribute_value){
     $output[$attribute_value][$attribute_id][] = $product_id;
    }

    // optionaly filter for dup product ids
    //$output[$attribute_value][$attribute_id] = array_unique($output[$attribute_value][$attribute_id], SORT_NUMERIC);
}
Question Mark
+1  A: 

Ok, if I get that right now, you have Products with four attributes: id, color, size and length, which you represent as

[product_id] => array (
    1 => [color_id],
    2 => [size_id],
    3 => [length_id]
)

Personally, I find this structure somewhat clumsy. Product id should be inside the array, because it is an attribute of product. Also, using index numbers instead of the property names, makes your products difficult to understand.

Now, what you want to do is, find all possible combinations of one of the attributes, e.g. all size_id and length_id when the user selects color_id for e.g. black.

You could do that with a finder method:

function findCombinationsByColorId($color_id, $products)
{
    $combos = array($color_id => array(
        'sizes'   => array(),
        'lengths' => array(),
        'products' => array()
    ));

    foreach($products as $productId => $product)
    {
         if($product[1] === $color_id) {
             $combos['sizes'][]    = $product[2];
             $combos['lengths'][]  = $product[3];
             $combos['products'][] = $productId;
         }
    }   
    return $combos;
}

Now, when you need to find all combinations for black and black is color_id of 0, you'd do findCombinationsByColorId(0, $productArray) and it would return an array holding all possible sizes, lengths and product Ids for this color.

You'd write additional functions for getting combinations by the other attributes. You could make the finder method generic, but I leave that up to you to figure out how.

What I dont get is why you are sorting this on the array level at all. I assume you get the possible products from somewhere, e.g. a database. So why not get the combos from there. That would probably be as easy as SELECT size_id, length_id, product_id from products where color_id = 0.

Gordon
A: 

The answer Gordon supplied is closest to what I'm looking for but is not very efficient given the way my initial array was formatted. Though I can't recall why now, my original purpose in using arrays was to avoid having to make a new query each time someone selects an option. The easy solution is just to proceed with the queries so that's what I'll do.

Jereme