Reputation: 2283
I'm having trouble creating the recipes for a multi-variate test. For example, if I wanted to test a combination of outfits and I had 3 different hats, shirts, and pants. I want to list every possible combination of them without duplicates. This is my thought process so far:
// outfit #1
$outfit[0][0] = "hat A ";
$outfit[0][1] = "shirt A ";
$outfit[0][2] = "pants A ";
// outfit #2
$outfit[0][0] = "hat B ";
$outfit[0][1] = "shirt B ";
$outfit[0][2] = "pants B ";
// outfit #3
$outfit[0][0] = "hat C ";
$outfit[0][1] = "shirt C ";
$outfit[0][2] = "pants C ";
function recipeMaker()
{
$i = 0;
$j = 0;
foreach ($outfit as $outfit_2)
{
foreach ($outfit_2 as $outfit_3)
{
...some magic here...
recipe[$i][$j] = ...something goes here...
$j++;
}
$i++;
}
}
foreach ($recipe as $r)
{
echo $r . "<br />";
}
Then it should output:
hat A shirt A pants A
hat B shirt A pants A
hat C shirt A pants A
hat A shirt B pants A
etc.
Upvotes: 0
Views: 65
Reputation: 1768
First, arrange your arrays into similar content (i.e all hats in one array, all shirts in another etc) to get this:
$hats[0] = 'Hat A';
$hats[1] = 'Hat B';
$hats[2] = 'Hat C';
$shirts[0] = 'Shirt A';
$shirts[1] = 'Shirt B';
$shirts[2] = 'Shirt C';
$pants[0] = 'Pants A';
$pants[1] = 'Pants B';
$pants[2] = 'Pants C';
$recipe = array();
Then use the foreach construct to loop through each element like so:
foreach ($hats as $hat) {
foreach ($shirts as $shirt) {
foreach ($pants as $pant) {
$recipe = $hat." ".$shirt." ".$pant;
}
}
}
foreach ($recipe as $r) {
echo $r."<br>";
}
Upvotes: 0
Reputation: 42527
You could go down the route of nesting foreach
loops, but what happens when you want to extend the outfit (e.g. add a list of ties)? Here's a solution which outputs the combinations available from any number of collections:
class Combiner {
protected $_collections;
protected $_combinations;
public function __construct() {
$args = func_get_args();
if (count(array_filter(array_map('is_array', $args))) !== func_num_args()) {
throw new Exception('Can only pass array arguments');
}
$this->_collections = $args;
}
protected function _getBatch(array $batch, $index) {
if ($index < count($this->_collections)) {
foreach ($this->_collections[$index] as $element) {
// get combinations of subsequent collections
$this->_getBatch(array_merge($batch, array($element)), $index + 1);
}
} else {
// got a full combination
$this->_combinations[] = $batch;
}
}
public function getCombinations() {
if (null === $this->_combinations) {
$this->_getBatch(array(), 0);
}
return $this->_combinations;
}
}
$hats = array('Hat A', 'Hat B', 'Hat C');
$shirts = array('Shirt A', 'Shirt B', 'Shirt C');
$pants = array('Pants A', 'Pants B', 'Pants C');
$combiner = new Combiner($hats, $shirts, $pants);
var_dump($combiner->getCombinations());
It moves along the list of types and picks one (say Hat A) then recursively builds the combinations of the rest of the types that go with that item. To add a new type it's as simple as passing another argument to the constructor.
Upvotes: 1