2

Ok, so say I have an array as follows:

$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(
 ),
 ),
);

I need to sort through this array and return all indexes of it in another array as an index, and the values of these arrays will be the title. So it should return an array as follows:

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

How can this be achieved easily? Basically, need the key of each array if a title is specified and need to populate both within another array.

asked Sep 28, 2011 at 19:26
1
  • What do you think how this can be done? Commented Sep 28, 2011 at 19:28

4 Answers 4

3

The following snippet loops over all of the arrays (recursively) to extract the key/title pairs.

$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);
answered Sep 28, 2011 at 20:16
Sign up to request clarification or add additional context in comments.

9 Comments

Wow, thanks, is the RecursiveIteratorIterator class built into all servers that have php enabled? Also, what version of PHP is required for this class to work in?
@SoLoGHoST: 1. Yes*, it is part of the Standard PHP Library. 2. PHP 5.1.0 (* I've yet to see any server deliberately disable the SPL)
Thanks salathe, this is beautiful!
+1 Iterating indeed is fun, sometimes the pre-build iterators don't catch what you need, but you can iterate yourself, too.
@hakre, lots of times the pre-built iterators don't quite fit our needs. Thankfully they're super easy to extend, rather than hack together some array-based alternative.
|
1

How can this be achieved easily?

  1. initialize an empty, new array
  2. foreach the $buttons array with key and value
    1. extract title from value
    2. set the key in the new array with the title
  3. done.

Edit: In case a recursive array iterator catches too much (identifying elements as children while they are not - just being some other array), and you don't want to write an extension of the recursive iterator class, stepping through all children can be solved with some "hand written" iterator like this:

$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;
}

This iterator is aware of the child key, so it will only iterate over childs if there are some concrete. You can control the order (children first, children last) by changing the order:

if ($children) $iterator = $children + $iterator;
- or - 
if ($children) $iterator += $children;
answered Sep 28, 2011 at 19:29

3 Comments

Well, wondering on what the advantage is of using this method? You say that the recursive array iterator might catch too much? Also, I know this method provides more compatibility, and doesn't seem to be any difference at all in speed or memory. What's the advantages and/or disadvantages between this method and using the class that salathe mentioned??
The ParentIterator returns all Iterator on arrays and objects that have at least one key/property that contains another array or object. In your case you only have children if it's an array and the key is named sub_buttons. That's what I meant with "catches too much" you might not want to traverse into any sub array / object just by var-type, but more specific. But this depends. And you would need to extend RecursiveArrayIterator/ParentIterator to only return the children you need. The code to do that, nobody wanted to write for the demo. I assume it's much larger.
Wow, thanks, am going with your answer on this definitely. Cause the sub_buttons needs to be defined and don't want to catch arrays within any other keys. Thank You! :)
0

I'm sure my answer is not most efficient, but using many foreach loops and if checks, it can be done. However, with my solution if you nested another array inside of say 'mlist_view' that you needed to get a title from, it would not work. My solution works for a max of 2 arrays inside of arrays within buttons. A better (and more general purpose solution) would probably involve recursion.

$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/>";
}
answered Sep 28, 2011 at 20:42

Comments

0

This works for your value of $buttons, fairly simple:

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>";

Which returns:

Array
(
 [mlist] => Members
 [mlist_view] => View the Member List
 [mlist_search] => Search for Members
 [home] => Home
 [help] => Help
)
answered Sep 28, 2011 at 21:25

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.