From: Robert Cummings on
Jim Lucas wrote:
> Daevid Vincent wrote:
>> Anyone have a function that will return an integer of the number of
>> dimensions an array has?
>>
>> I did some quick searches and came up with nothing.
>> The closest was here of someone asking the same thing, but his solution
>> isn't right:
>> http://www.bigresource.com/PHP-count-array-dimensions-VrIahx1b.html
>> http://php.net/manual/en/function.count.php
>>
>> From a human standpoint, it's easy to see, "oh, this is a TWO
>> dimensional"...
>>
>
> How about this... Using a slightly modified array that you posted, I came up
> with this in about 10 minutes
>
> <pre>I am working with the following data structure
>
> <?php
>
> $in = array(
> 0 => array(
> 0 => array('Flight Number', 'flight_number'),
> 1 => array(
> 0 => array('Timestamp Departure', 'timestamp_departure'),
> 1 => array('Timestamp Arrival', 'timestamp_arrival'),
> )
> ),
> 1 => array('Departure City', 'departure_city'),
> 2 => array('Arrival City', 'arrival_city'),
> );
>
> print_r($in);
>
> echo "\n\n";
>
> $max_depth = 0;
> $cur_depth = 0;
> function max_array_depth($ar) {
> global $cur_depth, $max_depth;
> if ( is_array($ar) ) {
> $cur_depth++;
> if ( $cur_depth > $max_depth ) {
> $max_depth = $cur_depth;
> }
> foreach ( $ar AS $row ) {
> max_array_depth($row);
> }
> $cur_depth--;
> }
> }
>
> max_array_depth($in);
>
> echo "Max depth of array is: {$max_depth}";
>
> ?></pre>
>
> http://www.cmsws.com/examples/php/testscripts/daevid(a)daevid.com/0002.php

Globals are dirty for this kind of recursive utility function. Here's a
cleaner example:
<?php

function get_array_depth( $array )
{
if( !is_array( $array ) )
{
return 0;
}

$maxDepth = 0;
foreach( $array as $value )
{
if( ($subDepth = get_array_depth( $value )) > $maxDepth )
{
$maxDepth = $subDepth;
}
}

return 1 + $maxDepth;
}

?>

Cheers,
Rob.
--
http://www.interjinn.com
Application and Templating Framework for PHP
From: Richard Quadling on
On 15 March 2010 23:45, Daevid Vincent <daevid(a)daevid.com> wrote:
> Anyone have a function that will return an integer of the number of
> dimensions an array has?

/**
* Get the maximum depth of an array
*
* @param array &$Data A reference to the data array
* @return int The maximum number of levels in the array.
*/
function arrayGetDepth(array &$Data) {
static $CurrentDepth = 1;
static $MaxDepth = 1;

array_walk($Data, function($Value, $Key) use(&$CurrentDepth, &$MaxDepth) {
if (is_array($Value)) {
$MaxDepth = max($MaxDepth, ++$CurrentDepth);
arrayGetDepth($Value);
--$CurrentDepth;
}
});

return $MaxDepth;
}

Extending Jim and Roberts comments to this. No globals. By using a
reference to the array, large arrays are not copied (memory footprint
is smaller). And by using array_walk, a separate internal pointer is
used, so no need to worry about losing your position on the array.

Something to watch out for though is recursion in the array. If a
value in the array is a reference to another part of the array, you
are going to loop around for ever.

$Data = array(&$Data);

for example, with the line ...

echo "$CurrentDepth, $MaxDepth, $Key\n";

in the callback function() will report 17701 before crashing out (no
stack error surprisingly enough).


Regards,

Richard Quadling.


--
-----
Richard Quadling
"Standing on the shoulders of some very clever giants!"
EE : http://www.experts-exchange.com/M_248814.html
EE4Free : http://www.experts-exchange.com/becomeAnExpert.jsp
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731
ZOPA : http://uk.zopa.com/member/RQuadling
From: Robert Cummings on


Richard Quadling wrote:
> On 15 March 2010 23:45, Daevid Vincent <daevid(a)daevid.com> wrote:
>> Anyone have a function that will return an integer of the number of
>> dimensions an array has?
>
> /**
> * Get the maximum depth of an array
> *
> * @param array &$Data A reference to the data array
> * @return int The maximum number of levels in the array.
> */
> function arrayGetDepth(array &$Data) {
> static $CurrentDepth = 1;
> static $MaxDepth = 1;
>
> array_walk($Data, function($Value, $Key) use(&$CurrentDepth, &$MaxDepth) {
> if (is_array($Value)) {
> $MaxDepth = max($MaxDepth, ++$CurrentDepth);
> arrayGetDepth($Value);
> --$CurrentDepth;
> }
> });
>
> return $MaxDepth;
> }
>
> Extending Jim and Roberts comments to this. No globals. By using a
> reference to the array, large arrays are not copied (memory footprint
> is smaller).

Using a reference actually increases overhead. References in PHP were
mostly useful in PHP4 when assigning objects would cause the object to
be copied. But even then, for arrays, a Copy on Write (COW) strategy was
used (and is still used) such that you don't copy any values. Try it for
yourself:

<?php

$copies = array();
$string = str_repeat( '*', 1000000 );

echo memory_get_usage()."\n";
for( $i = 0; $i < 1000; $i++ )
{
$copies[] = $string;
}
echo memory_get_usage()."\n";

?>

Cheers,
Rob.
--
http://www.interjinn.com
Application and Templating Framework for PHP
From: Peter Lind on
This is one example where references actually decrease memory usage.
The main reason is the recursive nature of the function. Try

<?php

echo memory_get_usage() . PHP_EOL;
$array = range(0,1000000);
$array[10] = range(0,10);
$array[20] = range(0,10);
$array[30] = range(0,10);
$array[40] = range(0,10);
$array[50] = range(0,10);
$array[60] = range(0,10);
$array[70] = range(0,10);
$array[80] = range(0,10);
$array[90] = range(0,10);
$array[100] = range(0,10);
echo memory_get_usage() . PHP_EOL;
carray($array);
function carray ($array)
{
foreach ($array as $value)
{
if (is_array($value)) carray($value);
}
echo memory_get_usage() . PHP_EOL;
echo count($array) . PHP_EOL;
}
echo memory_get_usage() . PHP_EOL;

And then compare with:

<?php

echo memory_get_usage() . PHP_EOL;
$array = range(0,1000000);
$array[10] = range(0,10);
$array[20] = range(0,10);
$array[30] = range(0,10);
$array[40] = range(0,10);
$array[50] = range(0,10);
$array[60] = range(0,10);
$array[70] = range(0,10);
$array[80] = range(0,10);
$array[90] = range(0,10);
$array[100] = range(0,10);
echo memory_get_usage() . PHP_EOL;
carray($array);
function carray (&$array)
{
$i = 0;
foreach ($array as $value)
{
if (is_array($value)) carray($value);
}
echo memory_get_usage() . PHP_EOL;
echo count($array) . PHP_EOL;
}
echo memory_get_usage() . PHP_EOL;

The memory usage spikes in the first example when you hit the second
array level - you don't see the same spike in the second example.

Regards
Peter

On 16 March 2010 15:46, Robert Cummings <robert(a)interjinn.com> wrote:
>
>
> Richard Quadling wrote:
>>
>> On 15 March 2010 23:45, Daevid Vincent <daevid(a)daevid.com> wrote:
>>>
>>> Anyone have a function that will return an integer of the number of
>>> dimensions an array has?
>>
>> /**
>>  * Get the maximum depth of an array
>>  *
>>  * @param array &$Data A reference to the data array
>>  * @return int The maximum number of levels in the array.
>>  */
>> function arrayGetDepth(array &$Data) {
>>        static $CurrentDepth = 1;
>>        static $MaxDepth = 1;
>>
>>        array_walk($Data, function($Value, $Key) use(&$CurrentDepth,
>> &$MaxDepth) {
>>                if (is_array($Value)) {
>>                        $MaxDepth = max($MaxDepth, ++$CurrentDepth);
>>                        arrayGetDepth($Value);
>>                        --$CurrentDepth;
>>                }
>>        });
>>
>>        return $MaxDepth;
>> }
>>
>> Extending Jim and Roberts comments to this. No globals. By using a
>> reference to the array, large arrays are not copied (memory footprint
>> is smaller).
>
> Using a reference actually increases overhead. References in PHP were mostly
> useful in PHP4 when assigning objects would cause the object to be copied..
> But even then, for arrays, a Copy on Write (COW) strategy was used (and is
> still used) such that you don't copy any values. Try it for yourself:
>
> <?php
>
> $copies = array();
> $string = str_repeat( '*', 1000000 );
>
> echo memory_get_usage()."\n";
> for( $i = 0; $i < 1000; $i++ )
> {
>    $copies[] = $string;
> }
> echo memory_get_usage()."\n";
>
> ?>
>
> Cheers,
> Rob.
> --
> http://www.interjinn.com
> Application and Templating Framework for PHP
>
> --
> PHP General Mailing List (http://www.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>



--
<hype>
WWW: http://plphp.dk / http://plind.dk
LinkedIn: http://www.linkedin.com/in/plind
Flickr: http://www.flickr.com/photos/fake51
BeWelcome: Fake51
Couchsurfing: Fake51
</hype>
From: Robert Cummings on
Peter Lind wrote:
> This is one example where references actually decrease memory usage.
> The main reason is the recursive nature of the function. Try
>
> <?php
>
> echo memory_get_usage() . PHP_EOL;
> $array = range(0,1000000);
> $array[10] = range(0,10);
> $array[20] = range(0,10);
> $array[30] = range(0,10);
> $array[40] = range(0,10);
> $array[50] = range(0,10);
> $array[60] = range(0,10);
> $array[70] = range(0,10);
> $array[80] = range(0,10);
> $array[90] = range(0,10);
> $array[100] = range(0,10);
> echo memory_get_usage() . PHP_EOL;
> carray($array);
> function carray ($array)
> {
> foreach ($array as $value)
> {
> if (is_array($value)) carray($value);
> }
> echo memory_get_usage() . PHP_EOL;
> echo count($array) . PHP_EOL;
> }
> echo memory_get_usage() . PHP_EOL;
>
> And then compare with:
>
> <?php
>
> echo memory_get_usage() . PHP_EOL;
> $array = range(0,1000000);
> $array[10] = range(0,10);
> $array[20] = range(0,10);
> $array[30] = range(0,10);
> $array[40] = range(0,10);
> $array[50] = range(0,10);
> $array[60] = range(0,10);
> $array[70] = range(0,10);
> $array[80] = range(0,10);
> $array[90] = range(0,10);
> $array[100] = range(0,10);
> echo memory_get_usage() . PHP_EOL;
> carray($array);
> function carray (&$array)
> {
> $i = 0;
> foreach ($array as $value)
> {
> if (is_array($value)) carray($value);
> }
> echo memory_get_usage() . PHP_EOL;
> echo count($array) . PHP_EOL;
> }
> echo memory_get_usage() . PHP_EOL;
>
> The memory usage spikes in the first example when you hit the second
> array level - you don't see the same spike in the second example.
>
> Regards
> Peter

Doh, forgot about that :)

Cheers,
Rob.
--
http://www.interjinn.com
Application and Templating Framework for PHP