Flatten Nested Arrays Using PHP

Written by David Walsh on Friday, August 22, 2008


While browing 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($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.


Epic Discussion

Commenter Avatar August 22 / #
Alan says:

Here is another function without the need for recursion.

function array_flatten($array, $maintain_keys=false) {
$array = print_r($array, true);
preg_match_all(“/[(.+?)].*?\=>(.+?)\n/”, $array, $matches);
$array = array();
foreach ($matches[0] as $k=>$v) {
$key = trim($matches[1][$k]);
$value = trim($matches[2][$k]);
if (preg_match(“/^array$/i”, $value)) continue;
if (array_key_exists($key, $array) || !$maintain_keys) {
$array[] = $value;
} else $array[$key] = $value;
}
return $array;
}

$arr = array(‘alpha’=>’a',’b',array(array(array(‘beta’=>’x'),’alpha’=>’y',’z')),array(array(‘p’)));
echo ” . print_r($arr, true) . ”;
echo ” . print_r(array_flatten($arr) , true) . ”;
echo ” . print_r(array_flatten($arr, true) , true) . ”;

Commenter Avatar October 17 / #
Harsha M V says:

Wonder if the array keys will be the same when used with mysql_fetch_assoc

Commenter Avatar January 10 / #

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:

function array_flatten ($array)
{
$i = 0;
while ($i < count ($array))
{
while (is_array ($array[$i]))
{
if (!$array[$i])
{
array_splice ($array, $i, 1);
--$i;
break;
}
else
{
array_splice ($array, $i, 1, $array[$i]);
}
}
++$i;
}
return $array;
}

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

Commenter Avatar July 15 / #
Alexandre Valiquette says:

Replace line #5 from

for($x = 0; $x <= count($array); $x++)

to

for($x = 0; $x < count($array); $x++)

(<= become <)
otherwise you get a notice “error” (Undefined offset) for every array fetched by the function.

Commenter Avatar July 27 / #

I did a different approach, since the requirement was also different, and the outcome is boasted
about at php-trivandrum, as function array_flatten

Commenter Avatar September 10 / #
Manu says:

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:

function array_flatten($array, $return=array()) {
foreach ($array AS $key => $value) {
if(is_array($value))
{
$return = array_flatten($value,$return);
}
else
{
if($value)
{
$return[] = $value;
}
}
}
return $return;

}

So $myarray = array(‘a’,'b’,array(array(‘test’ => array(‘x’),’y',’nested2′ => ‘z’)),array(‘nested3′ => array(‘p’))) will also work as expected.

Commenter Avatar November 05 / #

David! You just saved me hours!

Be Heard!

I want to hear what you have to say! Share your comments and questions below.

Name*:
Email*:
Website:  


© David Walsh 2007-2010. Contact David Walsh. Powered by the remarkable MooTools javascript framework.