Список с отступом к многомерному массиву

Я был удивлен, не найдя ответа на это на SO (или в другом месте в Интернете, если на то пошло). Это относится к вложенному отступу, который я хочу преобразовать в многомерный массив в соответствии с уровнем отступов.

В качестве примера, вот несколько примеров ввода:

Home Products Product 1 Product 1 Images Product 2 Product 2 Images Where to Buy About Us Meet the Team Careers Contact Us 

В идеале я хотел бы передать это в некоторую (рекурсивную?) Функцию и получить следующий результат:

 array( 'Home' => array(), 'Products' => array( 'Product 1' => array( 'Product 1 Images' => array(), ), 'Product 2' => array( 'Product 2 Images' => array(), ), 'Where to Buy' => array(), ), 'About Us' => array( 'Meet the Team' => array(), 'Careers' => array(), ), 'Contact Us' => array(), ); 

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

Solutions Collecting From Web of "Список с отступом к многомерному массиву"

Поскольку пока неясно, пытаетесь ли вы читать какую-либо данную структуру (html-dom) или из данной строки в виде обычного текста, я предположил, что это строка, которую вы пытаетесь проанализировать. Если да, попробуйте:

 <?php $list = 'Home Products Product 1 Product 1 Images Product 2 Product 2 Images Where to Buy About Us Meet the Team Careers Contact Us'; function helper($list, $indentation = ' ') { $result = array(); $path = array(); foreach (explode("\n", $list) as $line) { // get depth and label $depth = 0; while (substr($line, 0, strlen($indentation)) === $indentation) { $depth += 1; $line = substr($line, strlen($indentation)); } // truncate path if needed while ($depth < sizeof($path)) { array_pop($path); } // keep label (at depth) $path[$depth] = $line; // traverse path and add label to result $parent =& $result; foreach ($path as $depth => $key) { if (!isset($parent[$key])) { $parent[$line] = array(); break; } $parent =& $parent[$key]; } } // return return $result; } print_r(helper($list)); 

Демо: http://codepad.org/zgfHvkBV

Я не буду писать рекурсивную функцию, но чтобы указать вам в полезном направлении, взгляните на функцию substr_count PHP. Исходя из этого, вы можете подсчитать количество вкладок перед каждой строкой и сравнить их с количеством вкладок в предыдущей строке, чтобы выяснить, является ли это дочерним, родным и т. Д.

Неужели я единственный, у которого прекрасный образ, видя образец?

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

 $L = 4;//estimate depth level function tabbed_text_to_array ($raw, $L) { $raw = preg_replace("/^(\\t*)([^\\t\\n]*)\\n?/m" , "\t$1'$2' => array(\n" , $raw ); for( ; $L > 0 ; $L-- ) { for( $i=0; $i<3 ;$i++ ) { $preL = $L-1; $s = array( "^(\\t{{$L}})([^\\t\\),]*)(?=\\n\\t{{$L}}')", "^(\\t{{$L}})([^\\t\\),]*)(?=\\n(\\t{0,{$preL}})')", "^(\\t{{$L}})(\\),)(?=\\n(\\t{{$preL}})[^\t])" ); $r = array( "$1$2)," , "$1$2)\n" . str_repeat("\t",$preL) . ")," , "$1),\n$3)," ); $raw = preg_replace( "/$s[$i]/m" , $r[$i], $raw ); } } return "array(\n". $raw. ")\n);"; } 

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

Подобно размножению ячеек, он сначала добавляет в один проход наиболее распространенные вещи: кавычки, запятые и открывающие круглые скобки, а затем добавляет более мелкие детали в два прохода. Все они запускаются один раз для каждого указанного вами уровня (вы можете тратить код на поиск самого глубокого уровня для начала обработки, но достаточно догадки).

См. Рабочую демонстрацию / инструмент для преобразования текста с табуляцией в массив

Или посетите скрипт php со всеми проходами, чтобы вы могли расширить его.

В PHP-скриптах есть класс, который будет делать то, что вам нужно. Вы можете найти его здесь: Array To List

Он принимает многомерный массив и создает HTML.

обновленный

На самом деле это было противоположно этому. Для этого лучше всего использовать объект DOMDocument и загрузить HTML в представление объекта.

http://php.net/manual/en/domdocument.loadhtml.php