рассчитывать варианты продукта на основе групп опций и опций

Я пишу сайт электронной коммерции, и мне нужен хороший способ рассчитать варианты продукта. На сайте есть продукты, продукты могут иметь много групп опций, группы опций могут иметь множество опций.

Таким образом, у продукта с футболкой есть 3 группы опций и опции:

Размер: маленький, средний, большой,

Цвет: красный, синий, желтый, черный,

Материал: хлопок, нейлон,

который создает: маленький красный хлопок, маленький красный нейлон, маленький синий хлопок, маленький синий нейлон и т. д. и т. д.

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

    if(count($option_groups) > 1)
    {
        // start the variants up
        foreach($option_groups[0]->get_options() as $option)
        {
            $variants[] = array($option);
        }

        // go through every other option group to make combos
        for($x = 1; $x < count($option_groups); $x++)
        {
            $combos = array();

            foreach($variants as $variant)
            {
                $new = array();
                foreach($option_groups[$x]->get_options() as $option)
                {
                    $tmp        = $variant;
                    $tmp[]  = $option;
                    $new[]  = $tmp;
                }
                $combos[] = $new;
            }
            $variants = array();
            foreach($combos as $combo)
            {
                foreach($combo as $tmp)
                {
                    $variants[] = $tmp;
                }
            }
        }
    }

Это не очень чувствительно ко времени, но я бы хотел иметь более обслуживаемый фрагмент кода, это довольно грубо.

Также есть ли у этой проблемы (я чувствую, что это не оригинальная проблема, многие тележки так и поступают)? Я ничего не подтягивал в гугле по этой проблеме.

РЕДАКТИРОВАТЬ. Это то, к чему я пришел, он основан на решении profphp, но поддерживает мои объекты вместо того, чтобы давать мне варианты для каждого варианта, объединенные в строку. Все благодаря Profitphp!

private function _possible_combos($groups, $prefix = array())
{
    $result = array();
    $group  = array_shift($groups);
    foreach($group->get_options() as $selected)
    {
        if($groups)
        {
            $tmp            = $prefix;
            $tmp[]      = $selected;
          $result = array_merge($result, $this->_possible_combos($groups, $tmp));
        }
        else
        {
            $tmp            = $prefix;
            $tmp[]      = $selected;
          $result[] = $tmp; 
        }
    }

    return $result;
}

person Francis Yaconiello    schedule 06.09.2011    source источник
comment
Забавно, это вопрос, который я задаю на интервью, достаточно близко.   -  person Orbling    schedule 06.09.2011
comment
Не думаете ли вы, что получили хорошие (или, по крайней мере, лучше, чем я написал) ответы?   -  person Francis Yaconiello    schedule 06.09.2011
comment
Как евангелист Haskell, я не могу не похвастаться тем, что эта функция встроена: sequence [["small", "medium", "large"], ["red", "blue", "yellow", "black"], ["cotton", "nylon"]] = [["small","red","cotton"],["small","red","nylon"],["small","blue","cotton"],["small","blue","nylon"], {- and a bunch more ... -}]   -  person Daniel Wagner    schedule 07.09.2011
comment
Было бы очень здорово, если бы в php была функция для этого.   -  person Francis Yaconiello    schedule 07.09.2011


Ответы (2)


Это должно помочь:

<?

$data[]=array('shirt');
$data[]=array('red','yellow','black');
$data[]=array('small','medium','large');

$combos=possible_combos($data);

//calculate all the possible comobos creatable from a given choices array
function possible_combos($groups, $prefix='') {
    $result = array();
    $group = array_shift($groups);
    foreach($group as $selected) {
        if($groups) {
            $result = array_merge($result, possible_combos($groups, $prefix . $selected. ' '));
        } else {
            $result[] = $prefix . $selected;
        }
    }
    return $result;
}

echo count($combos) . "\n";
print_r($combos);

Протестировано: http://www.ideone.com/NZE5S

person profitphp    schedule 06.09.2011

Если это сайт электронной коммерции, я предполагаю, что ваши группы параметров уже находятся в базе данных SQL, так почему бы просто не позволить SQL выполнять комбинации за вас.

SELECT Size.Name, Color.Name, Material.Name FROM Size, Color, Material

Но что, если бы у вас были все варианты в одной таблице с внешним ключом для группы, в которой он находится ...

SELECT r1.Name, r2.Name, r3.Name 
FROM Options r1, Options r2, Options r3
WHERE r1.GroupID = 1 -- id for Size
    AND r2.GroupID = 2 -- id for Color
    AND r3.GroupID = 3 -- id for Material

Если у вас есть массив, содержащий идентификаторы групп, генерирующий приведенный выше оператор SQL, это тривиально (просто объединение нескольких сжатий строк).

person Louis Ricci    schedule 07.09.2011
comment
возможно, вы что-то знаете, но я думаю, что вы ошибаетесь с моей схемой: Product (id_product, ...), OptionGroup (id_option_group, id_product, name), Option (id_option, id_option_group, name) - группы опций для продукта. не поставил +1 за хорошую идею - person Francis Yaconiello; 07.09.2011