merlincam
merlincam

Reputation: 1928

php 5.3 convert array_walk_recursive

I have the following code, and I'd like to get away from the call-time pass-by-reference, (To convert from 5.2 to 5.3) but I'm not sure exactly sure what the correct way to do this would be (class, global variable, ?)

Here is a codepad that should have everything in it http://codepad.org/ombgFPMR

<?php

function count_things($item, $key, $total) {
    $total++;
}

$counts = array(100 => 1,
            101 => 1,
            102 => array(
                106 => 1,
                107 => 1
            ),
            103 => 1,
            104 => 1,
            105 => array(
                108 => 1,
                109 => array(
                    110 => 1,
                    111 => 1,
                    112 => 1
                )
            )
        );

foreach($counts as $key => $count) {
    $total = 0;

    if(is_array($count)) {
            $total++;
            /* The below is a logic error. Array elements that contain arrays do not get
               the callback function called on them. Therefore, any children with children
               of their own will not be counted. In the output of this paste,
               the final key, $final_counts[105]['total'], should have a value of 6, but it
               actually has a value of 5. */
    array_walk_recursive($count, 'count_things', &$total);
} else {
            $total = $count;
    }

    $final_counts[$key]['total'] = $total;
}   

print_r($final_counts);

?>

Output looks like:

Array
(
[100] => Array
    (
        [total] => 1
    )

[101] => Array
    (
        [total] => 1
    )

[102] => Array
    (
        [total] => 3
    )

[103] => Array
    (
        [total] => 1
    )

[104] => Array
    (
        [total] => 1
    )

[105] => Array
    (
        [total] => 5
    )

)

Upvotes: 4

Views: 1444

Answers (1)

Cameron Martin
Cameron Martin

Reputation: 6012

You can use count with COUNT_RECURSIVE flag.

You should use closures for this, these were introduced in 5.3.0 so they should work.

<?php

$counts = array(
    100 => 1,
    101 => 1,
    102 => array(
        106 => 1,
        107 => 1
    ),
    103 => 1,
    104 => 1,
    105 => array(
        108 => 1,
        109 => array(
            110 => 1,
            111 => 1,
            112 => 1
        )
    )
);

$final_counts = array();

foreach($counts as $key => $count) {

    if(is_array($count)) {
        $total = 1;
        array_walk_recursive($count, function() use (&$total) {
            $total++;
        });
    } else {
        $total = $count;
    }

    $final_counts[$key]['total'] = $total;
}

print_r($final_counts);

I might be able to provide a better solution if you put your problem in context.

Upvotes: 3

Related Questions