2015-01-23 3 views
2

У меня это как строковый ввод.Преобразование строки в многомерный массив в PHP

$str = '[2]Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis vulputate cursus nulla, at rhoncus ante egestas vitae. [3]Cras euismod aliquet hendrerit. [3]Integer tortor lorem, suscipit a ante id, faucibus iaculis dolor. Sed aliquet, erat sit amet porta efficitur, eros lorem hendrerit purus, eget pellentesque lacus sapien ut dolor. [3]Donec eget accumsan velit. [4]Vestibulum consectetur enim in nunc fermentum lacinia. Maecenas fermentum rutrum sodales. Quisque vulputate, dolor tempus luctus cursus, massa urna ultrices odio, non dictum sem nulla ac mi. Quisque egestas tellus velit, non elementum lorem consequat id. Proin bibendum feugiat mollis. Sed vel odio neque. [4]Tempo. [2]Phasellus ut mauris purus. Quisque vel tortor erat. [2]Donec eget accumsan velit.'; 

И я пытаюсь получить на это ...

array (
[0] => array (//First [2] and everything below 
    [0] => Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis vulputate cursus nulla, at rhoncus ante egestas vitae. 
    [1] => array (//[3]s that belong to first [2] 
     [0] => Cras euismod aliquet hendrerit. //First [3] 
     [1] => Integer tortor lorem, suscipit a ante id, faucibus iaculis dolor. Sed aliquet, erat sit amet porta efficitur, eros lorem hendrerit purus, eget pellentesque lacus sapien ut dolor. //Second [3] 
     [2] => array (//Third [3] and everything below 
      [0] => Donec eget accumsan velit. 
      [1] => array (
       [0] => Vestibulum consectetur enim in nunc fermentum lacinia. Maecenas fermentum rutrum sodales. Quisque vulputate, dolor tempus luctus cursus, massa urna ultrices odio, non dictum sem nulla ac mi. Quisque egestas tellus velit, non elementum lorem consequat id. Proin bibendum feugiat mollis. Sed vel odio neque. 
       [1] => Tempo. 
       ) 
      ) 
     ) 
[1] => Phasellus ut mauris purus. Quisque vel tortor erat. //Second [2] 
[2] => Donec eget accumsan velit. //Third [2] 

)

Я пробовал все, что я знал и мог найти @ php.net и везде, но Я потратил около шести часов на это, и я все еще застрял. Я попытался взорвать, preg_replace, array_walk_recursive (вместе с взрывом), перейдя от самой большой иерархии к меньшей (лучшие результаты до сих пор) и наоборот, но ничего. Как преобразовать строку в многомерный массив в PHP, задав иерархию по тегам в строке?

Большое спасибо!

+2

Вам нужно сделать, это рекурсивно: сначала взорвать на '[2]', затем _walk_ результирующий массив, расщепляющийся на '[3]', пройдя результирующее разбиение массива на '[4]' и т. д., пока вы не получите пустой на любом уровне, прежде чем переходить к следующему –

+0

Эй, Марк, спасибо за быстрый ответ! Каждый раз, когда я пытался взорваться, у меня было первое '[3]' s на том же уровне массива, что и родительский '[2]'. Только '[3]', у которого '[4]' под ним было передано (позже, другим взрывом) на более низкий уровень, что привело к той же самой проблеме, только ниже более глубокой в ​​массиве. – Holokinesis

+0

Я получил уведомление о вашем ответе, Марк, но, похоже, теперь он ушел. Что-то пошло не так? @StackOverflow? – Holokinesis

ответ

0

Этот код

$str = '<your_string>'; 

function stringToArray($str, $delimiter = 2, $isFirst = false) { 
    $delimiterStr = "[{$delimiter}]"; 
    $outArr = array(); 
    if (strpos($str,$delimiterStr)!==false) { 
     $outArr = explode($delimiterStr, $str);   
     $isFirstElement = true; 
     $tempArr = array(); 
     $key = 0; 
     foreach ($outArr AS $v) { 

      if (!empty($v)) 
      { 
       if ($isFirstElement) { 
        $tempArr[$key] = stringToArray($v, $delimiter+1); 
        $key++; 
       } else { 
        $tempArr[$key][] = stringToArray($v, $delimiter+1); 
       }              
      } 
      $isFirstElement = false;         
     } 
     $outArr = $tempArr;  
    } 
    if (!$outArr) {return trim($str);} else {return $outArr;} 
} 

$elements = stringToArray($str); 
print_r($elements[0]); 

вернется

Array 
(
[0] => Array 
    (
     [0] => Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis vulputate cursus nulla, at rhoncus ante egestas vitae. 
     [1] => Array 
      (
       [0] => Cras euismod aliquet hendrerit. 
       [1] => Integer tortor lorem, suscipit a ante id, faucibus iaculis dolor. Sed aliquet, erat sit amet porta efficitur, eros lorem hendrerit purus, eget pellentesque lacus sapien ut dolor. 
       [2] => Array 
        (
         [0] => Donec eget accumsan velit. 
         [1] => Array 
          (
           [0] => Vestibulum consectetur enim in nunc fermentum lacinia. Maecenas fermentum rutrum sodales. Quisque vulputate, dolor tempus luctus cursus, massa urna ultrices odio, non dictum sem nulla ac mi. Quisque egestas tellus velit, non elementum lorem consequat id. Proin bibendum feugiat mollis. Sed vel odio neque. 
           [1] => Tempo. 
          ) 

        ) 

      ) 

    ) 

[1] => Phasellus ut mauris purus. Quisque vel tortor erat. 
[2] => Donec eget accumsan velit. 
) 
+0

Спасибо, Энди! Это сделал трюк! – Holokinesis

0
$str = '[2]Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis vulputate cursus nulla, at rhoncus ante egestas vitae. [3]Cras euismod aliquet hendrerit. [3]Integer tortor lorem, suscipit a ante id, faucibus iaculis dolor. Sed aliquet, erat sit amet porta efficitur, eros lorem hendrerit purus, eget pellentesque lacus sapien ut dolor. [3]Donec eget accumsan velit. [4]Vestibulum consectetur enim in nunc fermentum lacinia. Maecenas fermentum rutrum sodales. Quisque vulputate, dolor tempus luctus cursus, massa urna ultrices odio, non dictum sem nulla ac mi. Quisque egestas tellus velit, non elementum lorem consequat id. Proin bibendum feugiat mollis. Sed vel odio neque. [4]Tempo. [2]Phasellus ut mauris purus. Quisque vel tortor erat. [2]Donec eget accumsan velit.'; 

$counter = 2; 
function splitLevel($str, $counter) { 
    if (strpos($str, '['.$counter.']') === false) { 
     return $str; 
    } 
    $split = array_values(
     array_filter(
      explode('['.$counter.']', $str) 
     ) 
    ); 

    array_walk(
     $split, 
     function(&$value) use ($counter) { 
      $value = splitLevel($value, ++$counter); 
     } 
    ); 

    if (($counter > 2) && (count($split) > 1)) { 
     $first = array_shift($split); 
     $split = array($first, $split); 
    } 
    return $split; 
} 
$array = splitLevel($str, $counter); 

var_dump($array); 

дает

array(3) { 
    [0]=> 
    array(2) { 
    [0]=> 
    string(117) "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis vulputate cursus nulla, at rhoncus ante egestas vitae. " 
    [1]=> 
    array(3) { 
     [0]=> 
     string(32) "Cras euismod aliquet hendrerit. " 
     [1]=> 
     string(179) "Integer tortor lorem, suscipit a ante id, faucibus iaculis dolor. Sed aliquet, erat sit amet porta efficitur, eros lorem hendrerit purus, eget pellentesque lacus sapien ut dolor. " 
     [2]=> 
     array(2) { 
     [0]=> 
     string(27) "Donec eget accumsan velit. " 
     [1]=> 
     array(2) { 
      [0]=> 
      string(306) "Vestibulum consectetur enim in nunc fermentum lacinia. Maecenas fermentum rutrum sodales. Quisque vulputate, dolor tempus luctus cursus, massa urna ultrices odio, non dictum sem nulla ac mi. Quisque egestas tellus velit, non elementum lorem consequat id. Proin bibendum feugiat mollis. Sed vel odio neque. " 
      [1]=> 
      string(7) "Tempo. " 
     } 
     } 
    } 
    } 
    [1]=> 
    string(52) "Phasellus ut mauris purus. Quisque vel tortor erat. " 
    [2]=> 
    string(26) "Donec eget accumsan velit." 
} 

Так просто добавить немного дополнительной логики, чтобы урезать конечные пробелы, и вы должны быть хорошо

+0

Это замечательно, Марк! Огромное спасибо. Он работает как очарование на моем домашнем сервере (PHP5.4.37). Теперь я только что узнал, что мой общий сервер работает с PHP5.2.42, поэтому я не могу запускать анонимные функции. Как я могу вызвать array_walk и правильно передать параметры для именованной функции? – Holokinesis

+0

Вы действительно должны обновлять свой общедоступный сервер, PHP 5.2 - это конец жизни еще в 2011 году, и даже PHP 5.3 составляет 5 месяцев назад. –

+0

Обратите внимание, что ответ, данный @axiac, почти идентичен моему собственному, так как он работает, и он показывает, как избежать закрытия для более ранних версий PHP –

0
// The string to parse 
$str = '[2]Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis vulputate cursus nulla, at rhoncus ante egestas vitae. [3]Cras euismod aliquet hendrerit. [3]Integer tortor lorem, suscipit a ante id, faucibus iaculis dolor. Sed aliquet, erat sit amet porta efficitur, eros lorem hendrerit purus, eget pellentesque lacus sapien ut dolor. [3]Donec eget accumsan velit. [4]Vestibulum consectetur enim in nunc fermentum lacinia. Maecenas fermentum rutrum sodales. Quisque vulputate, dolor tempus luctus cursus, massa urna ultrices odio, non dictum sem nulla ac mi. Quisque egestas tellus velit, non elementum lorem consequat id. Proin bibendum feugiat mollis. Sed vel odio neque. [4]Tempo. [2]Phasellus ut mauris purus. Quisque vel tortor erat. [2]Donec eget accumsan velit.'; 

// Parse the string, start with level 2 
$array = analyze($str, 2); 

// Ignore the fragment before the first '[2]' (it's empty) 
array_shift($array); 
// Display the list of fragments marked with '[2]` and their offspring 
print_r(current($array)); 


/** 
* Analyze the string $string, search for sections labeled with '[N]' 
* (N = $level). 
* Return an array with two elements: the text before the first '[N]' 
* marker and an array of the fragments that start with '[N]' marker. 
* Each fragment is parsed using the same function. 
* 
* Return the input string ($string) if it does not contain the marker. 
*/ 
function analyze($string, $level) 
{ 
    // The marker 
    $marker = '['.$level.']'; 

    // If the marker does not exist in the string then this is a leaf 
    if (strpos($string, $marker) === FALSE) { 
     // Return the input string 
     return $string; 
    } 

    // Split by section marker 
    $pieces = explode($marker, $string); 

    // Extract the first fragment; it is returned as is 
    $first = array_shift($pieces); 

    // Analyze the pieces, search for the next level 
    return array(
     $first,   // First fragment as is 
     array_map(  // Parse the rest using the same function (one level deeper) 
      function ($piece) use ($level) { 
       return analyze($piece, $level + 1); 
      }, 
      $pieces 
     ), 
    ); 
} 

Для того, чтобы использовать его в версиях PHP, прежде чем 5.3 (когда были введены анонимные функции), заменить последний блок кода (начиная с return array() с:

// Analyze the pieces, search for the next level 
$rest = array(); 
foreach ($pieces as $piece) { 
    $rest[] = analyze($piece, $level + 1); 
} 
return array($first, $rest); 
Смежные вопросы