Мне нужна помощь с преобразованием массива. У меня есть плоский массив, который выглядит так:
Array ( [0] => av_one_third [1] => av_icon_box [2] => /av_icon_box [3] => av_button [4] => av_icon_box [5] => /av_icon_box [6] => /av_one_third )
Значения этого массива являются фактически тегами из структуры, подобной xml. теперь мне нужно преобразовать этот массив в вложенный массив, который похож на следующую структуру:
[0] => Array ( [tag] => av_one_third [content] => Array ( [1] => Array ( [tag] => av_icon_box [content] => Array ( ) ) [2] => Array ( [tag] => av_button [content] => Array ( ) ) [3] => Array ( [tag] => av_icon_box [content] => Array ( ) ) ) ) etc
Есть простой способ сделать это? Моя первая идея заключалась в том, чтобы преобразовать массив в строку xml и использовать одну из встроенных функций XML php, но проблема в том, что самозакрывающиеся теги не помечены как таковые. В приведенном выше случае тот факт, что тег av_button не имеет закрывающих тегов тега функций анализа XML, которые я пробовал.
Некоторые дополнительные требования: – элементы могут содержать любое количество детей; – окончательный массив должен поддерживать правильный порядок
Существуют ли функции сортировки интеллектуального массива, которые могут легко решить эту проблему? Поблагодарили бы за любые намеки на это!
С наилучшими пожеланиями 🙂
У вашего массива типичная плоская структура, кодирующая иерархию. Но только если вы исправите ошибку там.
В основном он работает, как в следующем списке, с кодами PHP, включая исключения, указывающие, где ошибки содержатся в данных, чтобы вы могли исправить свои данные (вы можете найти похожие примеры на этом веб-сайте, например, см. Связанные вопросы в разделе Как преобразовать серию отношений родитель-ребенок в иерархическое дерево? ):
Инициализируйте корневую запись внутри массива деревьев. Там вы можете добавить детей.
$tree = ['children' => []];
Создайте массив указателей, в дереве которых первый элемент (уровень 0) указывает на корневой элемент дерева:
$pointers = [&$tree];
Теперь перейдите по каждой строке внутри данных:
foreach ($data as $index => $line) {
Решите, закрывает ли линия и сохраняет ли эти решения:
$close = '/' === $line[0];
Сохраните текущий счетчик указателей:
$count = count($pointers);
Если линия не закрывается, откройте новый элемент и продолжайте:
$pointers[$count] = ['tag' => $line, 'children' => []]; $pointers[$count - 1]['children'][] = & $pointers[$count]; continue;
В случае, если линия закрывается вместо этого, проверьте, соответствует ли тэг, и если да, удалите последний созданный указатель:
if ($count === 1) { throw new RuntimeException('Can not close on lowest level.'); } $name = $pointers[$count - 1]['tag']; if ($name !== substr($line, 1)) { throw new RuntimeException( "Invalid closing element <$line> (line #$index) in <$name>" ); } array_pop($pointers);
После того, как все строки были обработаны, как указано, все указатели могут быть удалены:
unset($pointers);
Результатом является массив, который можно найти у первых детей в корневом узле. Он может быть назначен переменной, а ненужные ссылки могут быть удалены:
$result = &$tree['children'][0]; unset($tree); print_r($result);
с$result = &$tree['children'][0]; unset($tree); print_r($result);
Если данные верны, это примерные выходы:
Array ( [tag] => av_one_third [children] => Array ( [0] => Array ( [tag] => av_icon_box [children] => Array ( ) ) [1] => Array ( [tag] => av_button [children] => Array ( ) ) [2] => Array ( [tag] => av_icon_box [children] => Array ( ) ) ) )