Создание рецептов для многовариантного теста в PHP? - PullRequest
0 голосов
/ 06 января 2012

У меня проблемы с созданием рецептов для многовариантного теста. Например, если я хотел проверить комбинацию нарядов, у меня было 3 разных шапки, рубашки и брюки. Я хочу перечислить все возможные комбинации без дубликатов. Это мой мыслительный процесс до сих пор:

// 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 />";
}

Тогда он должен вывести:

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.

Ответы [ 2 ]

1 голос
/ 06 января 2012

Вы могли бы пойти по пути вложения петель foreach, но что произойдет, если вы захотите расширить снаряжение (например, добавить список связей)? Вот решение, которое выводит комбинации, доступные из любого количества коллекций:

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());

Он перемещается по списку типов и выбирает один (скажем, шляпу A), а затем рекурсивно строит комбинации остальных типов, которые идут с этим элементом. Чтобы добавить новый тип, достаточно просто передать другой аргумент в конструктор.

0 голосов
/ 06 января 2012

Во-первых, разместите ваши массивы в похожий контент (т.е. все шляпы в одном массиве, все рубашки в другом и т. Д.), Чтобы получить это:

$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();

Затем используйте конструкцию foreach для циклического прохождения каждого элемента следующим образом:

foreach ($hats as $hat) {
    foreach ($shirts as $shirt) {
        foreach ($pants as $pant) {
            $recipe = $hat." ".$shirt." ".$pant;
        }
    }
}

foreach ($recipe as $r) {
    echo $r."<br>";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...