Flatten Nested Arrays Using PHP
While browsing the MooTools 1.2 source code, I found Array's flatten()
method. The flatten()
method takes nested arrays and "flattens" them all into one array. I asked myself how I could do that using PHP. The following is what I came up with.
The PHP
$myarray = array('a', 'b', array(array(array('x'), 'y', 'z')), array(array('p')));
function array_flatten($array,$return) {
for($x = 0; $x <= count($array); $x++) {
if(is_array($array[$x])) {
$return = array_flatten($array[$x], $return);
}
else {
if(isset($array[$x])) {
$return[] = $array[$x];
}
}
}
return $return;
}
$res = array_flatten($myarray, array());
The Result
Array
(
[0] => a
[1] => b
[2] => x
[3] => y
[4] => z
[5] => p
)
As you can see, array_flatten()
is used recursively to sniff out values from the original array. While I don't believe I've ever found myself with an array as nested as my example, it's good to know that I can extract the values if necessary.
![Camera and Video Control with HTML5]()
Client-side APIs on mobile and desktop devices are quickly providing the same APIs. Of course our mobile devices got access to some of these APIs first, but those APIs are slowly making their way to the desktop. One of those APIs is the getUserMedia API...
![39 Shirts – Leaving Mozilla]()
In 2001 I had just graduated from a small town high school and headed off to a small town college. I found myself in the quaint computer lab where the substandard computers featured two browsers: Internet Explorer and Mozilla. It was this lab where I fell...
![Image Reflections with CSS]()
Image reflection is a great way to subtly spice up an image. The first method of creating these reflections was baking them right into the images themselves. Within the past few years, we've introduced JavaScript strategies and CANVAS alternatives to achieve image reflections without...
![Google Extension Effect with CSS or jQuery or MooTools JavaScript]()
Both of the two great browser vendors, Google and Mozilla, have Extensions pages that utilize simple but classy animation effects to enhance the page. One of the extensions used by Google is a basic margin-top animation to switch between two panes: a graphic pane...
Here is another function without the need for recursion.
Wonder if the array keys will be the same when used with mysql_fetch_assoc
I went through this same issue with python a couple years ago[1]. Strangely, in all my years of using php, I never really needed flatten (well maybe a couple times it would have been handy). Python doesn’t handle recursion very well, so an iterative version is pretty much a necessity for it to be of any use. Here is a php translation of the python version I ended up using:
It’s much slower than your implementation (I assume because of the overhead of
array_splice
compared to python’s list.pop, since the python version performs comparably yours–it just doesn’t grok 2000 levels of recursion. In fact, when I use a translation of your php version, python dies very soon with “maximum recursion depth exceeded”).Ps. One small note, on 5.2.6 I get warnings about trying to accessing invalid indexes from the $array[$x] on lines 7 and 13–prefixing them with “@” prevents them from incurring the slowdown of invoking the warning of course (just thought I’d mention it for posterity).
__
[1] http://rightfootin.blogspot.com/2006/09/more-on-python-flatten.html
Replace line #5 from
to
(<= become <)
otherwise you get a notice “error” (Undefined offset) for every array fetched by the function.
I did a different approach, since the requirement was also different, and the outcome is boasted
about at php-trivandrum, as function array_flatten
Thanks for the post, this function is very handy.
Although, as we are retrieving a new array with new indexes it might be nice to have the same function that can flatten an associative array.
Here is your function modified to work with associative array:
So
$myarray = array('a','b',array(array('test' => array('x'),'y','nested2' => 'z')),array('nested3' => array('p')))
will also work as expected.and this keeps the keys!
David! You just saved me hours!
@Manu: if you replace $return[] = $value; with $return[$key] = $value; you get the preserve the index names of the source array(s). Don’t know if that’s everyone preference, but that was what I was looking for. If one wanted to make this optional, he could add a 3rd optional parameter to this function to indicate wether or not to preserve index names, like so:
And then run it like so to get a flattened array back with index names preserved:
And like this if you don’t want the index names preserved:
Great function, thanks David.
This is what i use, sposed to be faster than most methods:
NOTE: this function will omit zero values. for example:
array_flatten($test)
will output:to fix this problem, on line 13 use:
instead of:
here’s the whole function with the line replaced:
I know this post is a bit old, but here’s what I came up with – it’s super fast and concise.
Made a few improvements/simplifications, allowed associative arrays, etc.
function array_flatten(array $array, array $return = array()) {
foreach ($array as $k => $item) {
if (is_array($item))
$return = array_flatten($item, $return);
elseif ($item)
$return[] = $item;
}
return $return;
}
about the code on very top. their is an issue on using for loop, if the nested array have a key, it wont show the value. Instead use foreach loop. I have some revised on the code above, I hope it will help.
function array_flatten($array, $return)
{
foreach($array as $key => $val)
{
if(is_array($val))
{
$return = array_flatten($val, $return);
}
else
{
if($val)
{
$return[] = $val;
}
}
}
return $return;
}
$test= array(‘ddd’,
array(“hello” => ‘one’,’two’,array(array(‘inner’=>’innerval’, ‘innerval2’,array(‘key_inner’=>’inner_inner’)))),’ccc’,
array(‘a’,’b’),
array(‘dog’,’cat’)
);
$result = array_flatten($test,array());
print_r($result);
Output:
Array
(
[0] => ddd
[1] => one
[2] => two
[3] => innerval
[4] => innerval2
[5] => inner_inner
[6] => ccc
[7] => a
[8] => b
[9] => dog
[10] => cat
)
Replace
if ($array[$x])
With
if (in_array($x, array_keys($array)))
Or equivalent, otherwise a zero value won’t be returned.
Example:
var_dump( array_flatten(array(range(0, 5), 10)));
With you code will give
array
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5
5 => int 10
)
Instead of:
array
0 => int 0
1 => int 1
2 => int 2
3 => int 3
4 => int 4
5 => int 5
6 => int 10
)
Replace
if ($array[$x])
With
if (in_array($x, array_keys($array)))
Or equivalent, otherwise a zero value won’t be returned.
Example:
var_dump( array_flatten(array(range(0, 5), 10)));
With you code will give
array
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5
5 => int 10
Instead of:
array
0 => int 0
1 => int 1
2 => int 2
3 => int 3
4 => int 4
5 => int 5
6 => int 10
Replace
if ($array[$x])
With
if (in_array($x, array_keys($array)))
Or equivalent, otherwise a zero value won’t be returned.
Example:
var_dump( array_flatten(array(range(0, 5), 10)));
With you code will give
array
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5
5 => int 10
Instead of:
array
0 => int 0
1 => int 1
2 => int 2
3 => int 3
4 => int 4
5 => int 5
6 => int 10
Running
count()
inside a for loop isn’t the best way to go. The count should be run once and stored in a variable rather than computed for every iteration.Here’s one of the methods that is faster than the recursive iterator version above. Note that by design, this function does NOT preserve all data! You can tweak it to preserve the last entries encountered, by default it returns the first. Tested with random Google Maps API JSON data:
Worth noting, if you use that function (this is from the PHP Manual):
“If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended.
Values in the input array with numeric keys will be renumbered with incrementing keys starting from zero in the result array. “
Good function and best comments! Great!
Couldn’t figure out why the original function required a second parameter, so I rewrote the function.
I expanded upon Jaco’s implementation by having it now be able to handle string keys. I also added the option of defining how much flattening is done. The examples provided should make this more clear. It’s not perfect but I’ve found it useful.
Found this article useful, thanks. I made a couple of amends, considering the comments above.. and also to create new keys if sub-level index have the same name i.e
and
This was my solution:
why not just use array_merge?