Прошу помощи с генерацией многомерного массива

Zoidberg

Новичок
Прошу помощи с генерацией многомерного массива

Доброго вечера.
Бьюсь над задачей весь вечер - не могу найти простого подходящего решения, видимо, заработался. Прошу помочь, кто сможет.
Есть исходный массив:
PHP:
Array (0=> Array( 'A', 'AA', 'AAA', '10,15,20'), 1=>Array( 'A', 'AA', 'AAB', '10,20'), 2=>Array('A','AB','ABB','10,50'), 3=>Array( 'B', 'BB', 'BBA', '10,50'), 4=>Array( 'C', 'CC', '10') );
Длина массива-элемента произвольная, необходимо получить следующий многомерный ассоциативный массив:
PHP:
Array( 'A' => Array( 'AA' => Array( 'AAA' => Array (10,15,20), 'AAB' => Array (10,20) ), 'AB' => Array( 'ABB' => Array( 10,50 ) ) ), 'B' => ... , 'C' => ... )
 

Sender

Новичок
покажи сложное решение, раз простое не можешь найти. а мы уже посоветуем
 

Mr_Max

Первый класс. Зимние каникулы ^_^
Команда форума
Все. Спугнул.
 

Zoidberg

Новичок
Решения конечного не нашел, остановился на том, что, проходя элемент-массив, мне надо для каждого его элемента делать свой собственный массив, вот я не смог придумать как, т.е., допустим в первой итерации цикла я пишу $arr[$tmp_arr[$i]] = array(), а в последующих итерациях не могу понять как добавлять массив к элементу массива, созданного в прошлой итерации. Потом была идея собрать строку, а потом через eval ее прогнать, но некрасиво и стремно.
 

rotoZOOM

ACM maniac
Так как автор не указал все исходные условия, то придется сделать некоторое assume:
- данная структура является деревом, то есть не допускается наличие нескольких родителей у одного узла, варианты типа {(A,B), (A,C,B)} или {(A,B), (D,B)} считаются некорректными.

Это один из вариантов решения с использованием класса.
Сложность алгоритма линейная.

PHP:
/**
 * Узел дерева
 */
class Node
{
    public function  __construct($value)
    {
        $this->value = $value;
    }

    /**
     * Добавить ребенка
     * @param Node $node ребенок
     */
    public function add (Node $node)
    {
        $this->childs[$node->getValue()] = $node;
    }
    
    public function getValue()
    {
        return $this->value;
    }

    /**
     * Получить поддерево как один многомерный массив
     * @return array массив
     */
    public function getAsArray()
    {
        $result = array ();
        foreach ($this->childs as $key => $node)
        {
            $result[$key] = $node->getAsArray();
        }
        return $result;
    }

    public function getNumChild ()
    {
        return count ($this->childs);
    }

    private     $childs=array();
    private     $value;
}

/// исходные данные
$src = array (0=>array( 'A', 'AA', 'AAA', '10,15,20'),
              1=>array( 'A', 'AA', 'AAB', '10,20'),
              2=>array('A','AB','ABB','10,50'),
              3=>array( 'B', 'BB', 'BBA', '10,50'),
              4=>array( 'C', 'CC', '10') );

/// создаем корень дерева
$root = new Node (0);

/// массив всех узлов
$nodes = array();

/// массив тех значений, у которых точно есть родитель
$notroot = array();

/// перебираем все узлы
foreach ($src as $arr)
{
    $parent = null;
    foreach ($arr as $val)
    {
        /// если мы еще не знаем такого узел - создаем его
        if (!isset ($nodes[$val]))
        {
            $nodes[$val] = new Node($val);
        }

        /// если это не первый узел в массиве, то добавляем его в родителя
        if (!is_null($parent))
        {
            $parent->add ($nodes[$val]);
            /// ... ну и он, конечно, не является корнем
            $notroot[$val] = true;
        }
        /// текущий узел становится сам родителем для следующего элемента
        $parent = $nodes[$val];
    }
}

/// наполняем корень дерева узлами, у которых нет родителей
foreach ($nodes as $node)
{
    if (!isset ($notroot[$node->getValue()]))
    {
        $root->add($node);
    }
}

/// получаем все дерево, как массив
var_dump ($root->getAsArray());
Чтоб жизнь медом не казалась задание на дом: преобразовать строки в листьях дерева в массив чисел.
 

Zoidberg

Новичок
Большое спасибо!
Очень понятное и довольно простое решение. Его и буду использовать, хотя уже через строку и eval решил.
 

rotoZOOM

ACM maniac
Zoidberg Есть еще вариант, но только надо будет наложить дополнительное условие, а именно - первый элемент всех исходных массивов не имеет родителя в другом массиве. То есть не допустимы такие ситуации: {(A,B), (D,C,A)}
Для моего первого решения такого допущения делать не надо.
PHP:
/// исходные данные
$src = array (0=>array( 'A', 'AA', 'AAA', '10,15,20'),
              1=>array( 'A', 'AA', 'AAB', '10,20'),
              2=>array('A','AB','ABB','10,50'),
              3=>array( 'B', 'BB', 'BBA', '10,50'),
              4=>array( 'C', 'CC', '10') );


$result = array();
foreach ($src as $arr)
{
    $current = &$result;
    foreach ($arr as $el)
    {
        if (!isset ($current[$el]))
        {
            $current[$el] = array();
        }
        $current = &$current[$el];
    }
}

var_dump ($result);
 
Сверху