2009-04-20 3 views
0

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

Array(
    [0] => Array(
     [Category] => Array(
      [id] => 49 
      [name] => Poster 
     ) 
     [Child] => Array() 
    ) 
    [1] => Array(
     [Category] => Array(
      [id] => 48 
      [name] => Sticker 
     ) 
     [Child] => Array() 
    ) 
    [2] => Array(
     [Category] => Array(
      [id] => 46 
      [name] => Hat 
     ) 
     [Child] => Array() 
    ) 
    [3] => Array(
     [Category] => Array(
      [id] => 45 
      [name] => Hoodie 
     ) 
     [Child] => Array() 
    ) 
) 

Вы заметите, что $node['Child'] является пустым массивом во всех случаях. Это связано с тем, что я уже использовал array_filter() для фильтрации всех нелистовых узлов. Тем не менее, то, что я в конечном счете хочу иметь один одномерный массив из листовых узлов, как это:

Array(
    [49] => Poster 
    [48] => Sticker 
    [46] => Hat 
    [45] => Hoodie 
) 

Так что будет наиболее элегантным способом преобразования первого массива на второй массив?

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

[7] => Array(
    [Category] => Array(
     [id] => 36 
     [name] => Merch 
    ) 
    [Child] => Array(
     [0] => Array(
      [id] => 49 
      [name] => Poster 
     ) 
     [1] => Array(
      [id] => 48 
      [name] => Sticker 
     ) 
     [2] => Array(
      [id] => 40 
      [name] => Apparel 
     ) 
    ) 
) 

Наконец, я использую CakePHP, поэтому использование Set класса CakePHP является также приемлемым.

+0

Имеет ли этот контент, случайно возникший как XML? –

+0

Нет, это только структура данных, которую CakePHP предоставляет для запросов к базе данных. – Calvin

ответ

4

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

$cats = array(); 
foreach($categories as $c) { 
    $cats[$c['Category']['id']] = $c['Category']['name']; 
} 

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

+0

Простое решение часто является лучшим. Вы можете использовать вместо foreach. Но оба правильны. – OIS

1

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

preg_match_all("/\"name\";s:\d+:\"(.*?)\"/i", serialize($arr), $matches); 

print_r($matches[1]); 

Честно говоря, рекурсивные итерации являются лучшим выбором для ясности, даже если это не очень эффективные и краткие.

$arr = array(
    "0" => array(
     "Category" => array(
      "id" => 49 
      ,"name" => Poster 
     ) 
     ,"Child" => array() 
    ) 
    ,"1" => array(
     "Category" => array(
      "id" => 48 
      ,"name" => Sticker 
     ) 
     ,"Child" => array() 
    ) 
    ,"2" => array(
     "Category" => array(
      "id" => 46 
      ,"name" => Hat 
     ) 
     ,"Child" => array() 
    ) 
    ,"3" => array(
     "Category" => array(
      "id" => 45 
      ,"name" => Hoodie 
     ) 
     ,"Child" => array(
      "0" => array(
       "id" => 49 
       ,"name" => Poster 
      ) 
      ,"1" => array(
       "id" => 48 
       ,"name" => Sticker 
      ) 
      ,"2" => array(
       "id" => 40 
       ,"name" => Apparel 
      ) 
     ) 
    ) 
); 

findNames($arr, $names); 
echo '<pre>'; 
print_r($names); 
echo '</pre>'; 

function findNames($source, &$out) 
{ 
    foreach ($source as $value) 
    { 
     if (isset($value['name'])) 
     { 
      // Assumes that if $value['name'] exists, $value['id'] must also exist 
      $out[$value['id']] = $value['name']; 
      continue; 
     } 
     if (is_array($value)) 
     { 
      findNames($value, &$out); 
     } 
    } 
} 
Смежные вопросы