Быстрый рекурсивный поиск всех индексов в массиве

Итак, скажем, у меня есть массив следующим образом:

$buttons = array( 'mlist' => array( 'title' => 'Members', 'href' => $scripturl . '?action=mlist', 'show' => $context['allow_memberlist'], 'sub_buttons' => array( 'mlist_view' => array( 'title' => 'View the Member List', 'href' => $scripturl . '?action=mlist', 'show' => true, ), 'mlist_search' => array( 'title' => 'Search for Members', 'href' => $scripturl . '?action=mlist;sa=search', 'show' => true, 'is_last' => true, ), ), ), 'home' => array( 'title' => 'Home', 'href' => $scripturl, 'show' => true, 'sub_buttons' => array( ), 'is_last' => $context['right_to_left'], ), 'help' => array( 'title' => 'Help', 'href' => $scripturl . '?action=help', 'show' => true, 'sub_buttons' => array( ), ), ); 

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

 array( 'mlist' => 'Members', 'mlist_view' => 'View the Member List', 'mlist_search' => 'Search for Members', 'home' => 'Home', 'help' => 'Help', ); 

Как это можно добиться легко? В принципе, нужен ключ каждого массива, если указан заголовок и нужно заполнить его как внутри другого массива.

Как это можно добиться легко?

  1. инициализировать пустой, новый массив
  2. foreach массив $buttons с ключом и значением
    1. извлекать название из значения
    2. установите ключ в новом массиве с заголовком
  3. сделанный.

Изменить: в случае, если итератор рекурсивного массива слишком много ловит (идентифицируя элементы как дети, пока они не являются), а просто не является каким-то другим массивом), и вы не хотите писать расширение рекурсивного класса итератора, решил с помощью какого-то «рукописного» итератора:

 $index = array(); $childKey = 'sub_buttons'; $iterator = $buttons; while(list($key, $item) = each($iterator)) { array_shift($iterator); $index[$key] = $item['title']; $children = isset($item[$childKey]) ? $item[$childKey] : false; if ($children) $iterator = $children + $iterator; } 

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

 if ($children) $iterator = $children + $iterator; - or - if ($children) $iterator += $children; 

Следующий фрагмент обходит все массивы (рекурсивно), чтобы извлечь пары ключ / заголовок.

 $index = array(); $iterator = new RecursiveIteratorIterator(new ParentIterator(new RecursiveArrayIterator($buttons)), RecursiveIteratorIterator::SELF_FIRST); foreach ($iterator as $key => $value) { if (array_key_exists('title', $value)) { $index[$key] = $value['title']; } } var_dump($index); 

Я уверен, что мой ответ не самый эффективный, но с использованием многих циклов foreach и проверок можно сделать. Тем не менее, с моим решением, если вы вложили другой массив из «mlist_view», что вам нужно было получить титул, это не сработает. Мое решение работает для макс. 2 массивов внутри массивов внутри кнопок. Лучшее (и более общее решение), вероятно, потребует рекурсии.

 $result = array(); foreach($buttons as $field => $value) { foreach($value as $nF => $nV) { if($nF === 'title') { $result[$field] = $nV; } if(is_array($nV)) { foreach($nV as $name => $comp) { if(is_array($comp)) { foreach($comp as $nnF => $nnV) { if($nnF === 'title') { $result[$name] = $nnV; } } } } } } } foreach($result as $f => $v) { echo $f.": ".$v."<br/>"; } 

Это работает для вашего значения $ кнопок, довольно просто:

 function get_all_keys($arr) { if (!is_array($arr)) return array(); $return = array(); foreach (array_keys($arr) as $key) { if (is_array($arr[$key]) && array_key_exists('title', $arr[$key])) $return[$key] = $arr[$key]['title']; $return = array_merge($return, get_all_keys($arr[$key])); } return $return; } echo "<pre>"; print_r(get_all_keys($buttons)); echo "</pre>"; 

Что возвращает:

 Array ( [mlist] => Members [mlist_view] => View the Member List [mlist_search] => Search for Members [home] => Home [help] => Help )