How do I use a recursive array iterator to process a multidimensional array?
Ok, here is a quick something for you to figure out:
$data = array(
'title' => 'how to work with iterators',
'posts' => array(
array(
'title' => 'introduction to iterators',
'email' => '[email protected]'
), array(
'title' => 'extending iterators',
'email' => '[email protected]'
)
));
The main idea is to influence how the Iterator
returns the current
element. Iterators are stackable, so you should use a RecursiveArrayIterator
and wrap it into a RecursiveIteratorIterator
. To achieve custom functionality, you can either subclass the RecursiveIteratorIterator
(as shown below) or use additional iterators to decorate the RecursiveIteratorIterator
:
class PostFormatter extends RecursiveIteratorIterator
{
public function current()
{
$current = parent::current();
switch($this->key()) {
case 'email':
$current = strtolower($current);
break;
case 'title':
$current = ucwords($current);
break;
default:
break;
}
return $current;
}
}
Then you simply foreach
over the iterator
$it = new PostFormatter(new RecursiveArrayIterator($data));
foreach($it as $key => $post) {
echo "$key: $post", PHP_EOL;
}
and get
title: How To Work With Iterators
title: Introduction To Iterators
email: [email protected]
title: Extending Iterators
email: [email protected]
You can try to get the array back from the with iterator_to_array
or iterator_apply
functions. However, to get the values reapplied to the original array structure, you dont need an iterator:
array_walk_recursive($data, function(&$val, $key) {
switch($key) {
case 'title': $val = ucwords($val); break;
case 'email': $val = strtolower($val); break;
default: break;
}
});
print_r($data);
Note: exchange Lambda with Function name when using PHP<5.3
bcmcfc
JavaScript, JavaScript Does whatever a JavaScript does Is it Java? No, it's a script! Look out! It's JavaScript.
Updated on June 22, 2022Comments
-
bcmcfc almost 2 years
I'm trying to get something like this working:
function posts_formatter (&$posts){ foreach ($posts as $k => $v){ if (is_array($v)){ posts_formatter($v); }else{ switch (strtolower($k)){ # make email addresses lowercase case (strpos($k, 'email') !== FALSE): $posts[$k] = strtolower($v); break; # make postcodes uppercase case (strpos($k, 'postcode') !== FALSE): $posts[$k] = strtoupper($v); break; # capitalize certain things case (strpos($k, 'line1') !== FALSE): case (strpos($k, 'line2') !== FALSE): case (strpos($k, 'line3') !== FALSE): case (strpos($k, 'forename') !== FALSE): case (strpos($k, 'surname') !== FALSE): $posts[$k] = capitalize($v); break; } } } }
It will correctly go through the array and format the values but I can't get it to return them. I've played around with removing the
&
from the function declaration and adding a return at the end but it won't do anything.Additionally, I'm thinking perhaps using a
RecursiveArrayIterator
might be the way to go. However, despite the presence of a book right in front of me with a chapter on SPL Iterators its examples are useless towards being able to achieve what I'm trying to. How would I go about implementing one?Edit:
array ( 'user' => array ( 'title' => 'Mr.', 'forename' => 'lowercase', 'surname' => 'name', 'businessName' => 'some dude', 'telephone' => '07545464646', 'postcode' => 'wa1 6nj', 'line1' => 'blergh road', 'line2' => 'randomLY cApitaLIzed wOrds', 'line3' => '', ), 'email' => '[email protected]', 'address' => array ( 'postcode' => 'ab1 1ba', 'line1' => 'test road', 'line2' => 'testville', 'line3' => 'testshire', ), 'date' => '2010-09-30' )
-
bcmcfc over 13 yearsThanks for your help Gordon. Just one more quick Q- how do I amend it return the processed array with the original array structure intact?
-
bcmcfc over 13 yearsThanks for the detailed explanation.
-
Gordon over 13 years@bcmcfc You're welcome. I had to remove the iterator_to_array code because it wouldnt apply the changes to the inner arrays. I am sure you can do it somehow, but right now I cant fiddle with it (time constraints). Sorry.