2012-01-16 4 views
2

Я был удивлен, что не нашел ответа на это на 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(), 
); 

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

+5

как выглядит список с отступом, вкладки || пространства || html ... –

+0

Кажется, что метод отступа может быть передан (как строка, например) функции, которая строит этот массив массивов. – Crontab

ответ

9

Поскольку пока неясно, я пытаюсь прочитать из какой-либо определенной структуры (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

+0

Спасибо, Йоши. Прекрасно работает :-) –

-2

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

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

Обновленный

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

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

+0

Спасибо, но я за скриптом, который может сделать обратное тому, что вы описали. –

+0

О'кей, вы можете посмотреть на разбор его в DOMDocument в этом случае. Взгляните на loadHTML: http://php.net/manual/en/domdocument.loadhtml.php –

0

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

0

Am Я только один с красивым ума, видя картину?

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

$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() это. Это не так плохо, как кажется. Двойная обратная косая черта делает чтение труднее, но это просто.

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

Смотрите рабочее демо/tool to convert tab-indented text into array

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

Смежные вопросы