浏览一组数据的最佳方法

I'm looking at some cost information and I need a good way to display all the combinations. I'm not sure if I have to used nested foreach loops or something else.

I have 25 different items. item1 - item2 .. item 25

I have 6 bolts that are used in the construction of my items. bolt1 - bolt2 - bolt3 - bolt4 - bolt5 - bolt6 each bolt having a different cost.

All items can only use one type of bolt. Not a mixture, like 3 of bolt 1 and 3 of bolt 2.

  • 7 of the 25 items require 6 bolts.
  • 6 of the remaining require 5 bolts.
  • 3 of the remaining require 4 bolts.
  • 5 of the remaining require 3 bolts.
  • 3 of the remaining require 2 bolts.
  • The last 1 requires 1 bolt.

Here is where it gets tricky.

Each item with their number of bolts needs one of 4 accessory packs that have a different cost.

acc1 - acc2 - acc3 - acc4

Each item also needs one of 4 box stuffer. Each, with a different cost

stuffer1 - stuffer3 - stuffer3 - stuffer4

And finally, each item needs one of 3 wrappers. Each, with a different cost.

wrapper1 - wrapper2 - wrapper3

I need PHP to give me every possible combination of prices, for example.

foreach 6 bolt item{
(6 bolt1 * $cost) +  ($acc1Cost + $stuffer1Cost + $wrapper1Cost) = item1acc1stff1wra1COST
(6 bolt1 * $cost) +  ($acc2Cost + $stuffer1Cost + $wrapper1Cost) = item1acc2stff1wra1COST
(6 bolt1 * $cost) +  ($acc3Cost + $stuffer1Cost + $wrapper1Cost)  ..
(6 bolt1 * $cost) +  ($acc4Cost + $stuffer1Cost + $wrapper1Cost)  ..
(6 bolt1 * $cost) +  ($acc1Cost + $stuffer2Cost + $wrapper1Cost)  ..
(6 bolt1 * $cost) +  ($acc1Cost + $stuffer3Cost + $wrapper1Cost)
(6 bolt1 * $cost) +  ($acc1Cost + $stuffer4Cost + $wrapper1Cost)
(6 bolt1 * $cost) +  ($acc1Cost + $stuffer1Cost + $wrapper2Cost)
(6 bolt1 * $cost) +  ($acc1Cost + $stuffer1Cost + $wrapper3Cost)
(6 bolt2 * $cost) +  ($acc1Cost + $stuffer1Cost + $wrapper3Cost)
(6 bolt2 * $cost) +  ($acc1Cost + $stuffer1Cost + $wrapper3Cost)
..... all combinations
foreach 5 bolt item{
(5 bolts * $cost) +  (**$acc1Cost** + **$stuffer1Cost** **$wrapper1Cost**)
(5 bolts * $cost) +  (**$acc2Cost** + **$stuffer1Cost** **$wrapper1Cost**)
(5 bolts * $cost) +  (**$acc3Cost** + **$stuffer1Cost** **$wrapper1Cost**)
(5 bolts * $cost) +  (**$acc4Cost** + **$stuffer1Cost** **$wrapper1Cost**)

..so on to the end..
}

each type of item is sorted into different arrays that are divided by how many bolts they require.

$oneBolt = array(
bolt1 => cost,
...
);

Each of the other item groups are kept in their respective price arrays.

I realize I could write out all combinations like above, but how do I do this with loops? Is it smart to do it one way or another? Does PHP have a built in function for stuff like this? Please, any insight you can provide is appreciated. Is there another way I should be doing this?

I think your issue is more about content modelling than actual programming.

Have you considered using a mysql database to store these relationships? You'd have one table for the items, one table for the bolts, one table for the accessories, one table for stuffers and one table for wrappers.

Then, you should define the relationships between each object:

  • 1-to-1 : example: "one human as one set of eyes. One set of eyes can only belong to one human"
  • 1-to-many : example: "A human can only have one family"
  • many-to-1 : example: "a family can have many humans."
  • many-to-many : example: "a recipe can have many ingredients. An ingredients can have many recipes"

So, in your case:

Items / bolts relationship is : many-to-one Items / accessories is: one-to-one (afaik) etc.

When you've setup that, you need to produce middleware code (php for instance) that implements your "business logics": makes sure your restrictions are respected, and then calculate the price for each Item according to these restrictions.

I realize i'm answering to your request by taking you into a totally different direction, but that's how i would do it. I'd use a MVC Framework to speed up the development (cakephp, yii, codeigniter, etc.). Let me know if you need more information on this methodology.

Let see how to do it using Arrays, as you suggested. We'll use multi-dimensional arrays so you can store more info about each part besides its price (like name, provider, url, etc.).

$bolts = array();
$bolts[1] = array('price'=> 25);
$bolts[2] = array('price'=> 12);
$bolts[3] = array('price'=> 45);
$bolts[4] = array('price'=> 33);
$bolts[5] = array('price'=> 32);
$bolts[6] = array('price'=> 31);

$accessories = array();
$accessories[1] = array('price'=> 140);
$accessories[2] = array('price'=> 120);
$accessories[3] = array('price'=> 134);
$accessories[4] = array('price'=> 136);

$stuffer = array();
$stuffer[1] =array('price'=> 12);
$stuffer[2] =array('price'=> 12);
$stuffer[3] =array('price'=> 12);
$stuffer[4] =array('price'=> 12);

$wrapper = array();
$wrapper[1] =array('price'=> 12);
$wrapper[2] =array('price'=> 12);
$wrapper[3] =array('price'=> 12);

$items = array();
$items[1] = array('bolt'=> 3, 'bolt_amount'=>7, 'accessory'=>2, 'stuffer'=>4, 'wrapper'=>2);
// Do that for 25 items, each item is an array containing its relationships. Store the Index of the part in its own array so you can reference it when calculating the price.

$items[1]['price'] = ($items[1]['bolt_amount'] * $bolts[$items[1]['bolt']]['price']) + $accessories[$items[1]['accessory']]['price'] + $stuffer[$items[1]['stuffer']]['price'] + $wrapper[$items[1]['wrapper']]['price'];

echo $items[1]['price'];

// 7*45 + 120 + 12 + 12 = 459

That would be about the simplest - yet maintainable - way to write it.

As pixeline wrote it would be better if you use database. But if you want to use arrays i wrote few lines of code that should be useful for you.

// make combinations array
function combinations($data, &$all = array(), $group = array(), $val = null, $i = 0) {
    if (isset($val))
    {
        array_push($group, $val);
    }

    if ($i >= count($data))
    {
        $combination_price = array_product($group);
        array_push($all, array('combination' => $group, 'combination_price' => $combination_price));
    }
    else {
        foreach ($data[$i] as $v)
        {
            combinations($data, $all, $group, $v, $i + 1);
        }
    }

    return $all;
}

$bolts = array(
    25, // bolt 1 price
    30, // bolt 2 price
    40  // bolt 3 price
);

// array of items contains number of bolts and price
$items = array (
    array(
        'bolts_num' => 6,
        'bolt_price' => $bolts[0]
    ), 
    array(
        'bolts_num' => 6,
        'bolt_price' => $bolts[1]
    ), 
    array(
        'bolts_num' => 6,
        'bolt_price' => $bolts[2]
    ),  
);

$accessories = array(
    12, 16, 18, 20 //accessories prices
);

$stuffers = array(
    20, 10, 30, 40  //stuffers prices
);

$wrapper = array(
    11, 13, 17  //wrapper prices
);

// all combinations, use var_dump if you dont know what is inside
$combinations = combinations(array($accessories, $stuffers, $wrapper));

$item_combinations = array();

// join combinations and items and calculate final price
foreach ($items as $item_key => $item) {
    foreach($combinations as $combination) {
        $item_price = array_product($item);
        $item_combinations[] = array(
            'item_id' => $item_key,
            'combination' => $combination['combination'],
            'price' => $combination['combination_price'] + $item_price
        );
    }
}

var_dump($item_combinations);

What we do:

  1. create all accessories - stuffers - wrappers combinations and calculate price for every one combination (accessory*stuffer*wrapper). I used array_product function.
  2. join combinations and items. I calculated for each item its price (bolt * num) and added to combination price. I forget about item price so you should add item price also.

If you have any questions - ask.

See in action: http://codepad.viper-7.com/8fsVp6