Как рекурсивно создать многомерный массив? - PullRequest
2 голосов
/ 13 сентября 2009

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

config.debug.router.strictMode = true

Я хочу получить те же результаты, что и при наборе:

$arr = array('config' => array('debug' => array('router' => array('strictMode' => true))));

Эта проблема действительно заставляет меня ходить по кругу, любая помощь приветствуется. Спасибо!

Ответы [ 5 ]

4 голосов
/ 13 сентября 2009

Предположим, у нас уже есть ключ и значение в $key и $val, тогда вы можете сделать это:

$key = 'config.debug.router.strictMode';
$val = true;
$path = explode('.', $key);

Построение массива слева направо:

$arr = array();
$tmp = &$arr;
foreach ($path as $segment) {
    $tmp[$segment] = array();
    $tmp = &$tmp[$segment];
}
$tmp = $val;

И справа налево:

$arr = array();
$tmp = $val;
while ($segment = array_pop($path)) {
    $tmp = array($segment => $tmp);
}
$arr = $tmp;
4 голосов
/ 13 сентября 2009

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

$s = 'config.debug.router.strictMode = true';
list($parts, $value) = explode(' = ', $s);

$parts = explode('.', $parts);
while($parts) {
   $value = array(array_pop($parts) => $value);
}

print_r($parts);

Определенно переписать его, чтобы он имел проверку ошибок.

1 голос
/ 21 августа 2013

Мне очень нравится ответ JasonWolf на это.

Что касается возможных ошибок: да, но он дал отличную идею, теперь читатель должен сделать это пуленепробиваемым.

Моя потребность была немного более простой: из списка с разделителями создайте массив MD. Я немного изменил его код, чтобы получить именно это. Эта версия предоставит вам массив с определенной строкой или без нее или даже строку без разделителя.

Я надеюсь, что кто-то может сделать это еще лучше.

$parts = "config.debug.router.strictMode";

$parts = explode(".", $parts);

$value = null;

while($parts) {
  $value = array(array_pop($parts) => $value);
}


print_r($value);
1 голос
/ 13 сентября 2009

Гамбо ответ выглядит хорошо.

Однако похоже, что вы хотите проанализировать типичный файл .ini.

Подумайте об использовании библиотечного кода, а не обкатки собственного.

Например, Zend_Config прекрасно справляется с подобными вещами.

0 голосов
/ 13 сентября 2009
// The attribute to the right of the equals sign
$rightOfEquals = true; 

$leftOfEquals = "config.debug.router.strictMode";

// Array of identifiers
$identifiers = explode(".", $leftOfEquals);

// How many 'identifiers' we have
$numIdentifiers = count($identifiers);


// Iterate through each identifier backwards
// We do this backwards because we want the "innermost" array element
// to be defined first.
for ($i = ($numIdentifiers - 1); $i  >=0; $i--)
{

   // If we are looking at the "last" identifier, then we know what its
   // value is. It is the thing directly to the right of the equals sign.
   if ($i == ($numIdentifiers - 1)) 
   {   
      $a = array($identifiers[$i] => $rightOfEquals);
   }   
   // Otherwise, we recursively append our new attribute to the beginning of the array.
   else
   {   
      $a = array($identifiers[$i] => $a);
   }   

}

print_r($a);
...