10

I have an associative array that is I am creating from an ODBC query with the following code:

        while ($row=odbc_fetch_array($oexec)) {
        if(empty($group[$row['gmm']])) {
            $group[$row['gmm']] = array();
        }
        if(empty($group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']])) {
            $group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']] = array();
        }
        if(empty($group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']][$row['dept_catg_grp_desc']])) {
            $group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']][$row['dept_catg_grp_desc']] = array();
        }
        if(empty($group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']][$row['dept_catg_grp_desc']][$row['dept_category_desc']])) {
            $group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']][$row['dept_catg_grp_desc']][$row['dept_category_desc']] = array();
        }
        if(empty($group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']][$row['dept_catg_grp_desc']][$row['dept_category_desc']][$row['dept_subcatg_desc']])) {
            $group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']][$row['dept_catg_grp_desc']][$row['dept_category_desc']][$row['dept_subcatg_desc']] = array();
        }
        $group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']][$row['dept_catg_grp_desc']][$row['dept_category_desc']][$row['dept_subcatg_desc']]['total_ty_yest_sales'] = $row['total_ty_yest_sales'];
        $group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']][$row['dept_catg_grp_desc']][$row['dept_category_desc']][$row['dept_subcatg_desc']]['total_wo_dotcom_ty_yest_sales'] = $row['total_wo_dotcom_ty_yest_sales'];
        $group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']][$row['dept_catg_grp_desc']][$row['dept_category_desc']][$row['dept_subcatg_desc']]['east_ty_yest_sales'] = $row['east_ty_yest_sales'];
        $group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']][$row['dept_catg_grp_desc']][$row['dept_category_desc']][$row['dept_subcatg_desc']]['central_ty_yest_sales'] = $row['central_ty_yest_sales'];
        $group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']][$row['dept_catg_grp_desc']][$row['dept_category_desc']][$row['dept_subcatg_desc']]['west_ty_yest_sales'] = $row['west_ty_yest_sales'];
        $group[$row['gmm']][$row['acctg_dept_nbr'] . " - " . $row['acctg_dept_desc']][$row['dept_catg_grp_desc']][$row['dept_category_desc']][$row['dept_subcatg_desc']]['dotcom_ty_yest_sales'] = $row['dotcom_ty_yest_sales'];

    }

This gives me an array where:

$myArray = Array(GMM => Array(acctg_dept_nbr => Array(dept_category_desc => Array(dept_subcatg_desc => Array(value1,value2,value3)))))

I want to sum the values at every level. So for every acctg_dept_nbr[dept_category_desc][dept_subcatg_desc] I want to sum value1,value2,value3. Same for the GMM level and down to the dept_subcatg_desc level. Summing the dept_subcatg_desc level wasn't a problem. I dug around and found how to sum the dept_category_desc level, but am having trouble applying that method recursively.

Here is the code that puts the values into a table:

foreach($group as $gmm => $acctg_dept_nbrs) {
        echo "<tr class=\"header\">
        <td>" . $gmm . "</td>\n";

        foreach ($acctg_dept_nbrs as $acctg_dept_nbr => $dept_catg_grp_descs) {
                        echo "<tr class=\"header\">\n
            <td style=\"padding-left: 1em;\">" . $acctg_dept_nbr . "</td>\n";

            foreach($dept_catg_grp_descs as $dept_catg_grp_desc => $dept_category_descs) {
                echo "<tr class=\"header\">\n
                <td style=\"padding-left: 2em;\">" . $dept_catg_grp_desc . "</td>\n";
                                    //echo "<td>" . array_sum(array_walk_recursive($dept_category_descs,function($item) {return $item['total_ty_yest_sales'];})) . "</td>";
                foreach($dept_category_descs as $dept_category_desc => $dept_subcatg_descs) {
                    echo "<tr class=\"header\">\n
                    <td style=\"padding-left: 3em;\">" . $dept_category_desc . "</td>\n";
                                            echo "<td>" . array_sum(array_map(function($item) {return $item['total_ty_yest_sales'];},$dept_subcatg_descs)) . "</td>";
                                            echo "<td>" . array_sum(array_map(function($item) {return $item['east_ty_yest_sales'];},$dept_subcatg_descs)) . "</td>";
                                            echo "<td>" . array_sum(array_map(function($item) {return $item['central_ty_yest_sales'];},$dept_subcatg_descs)) . "</td>";
                                            echo "<td>" . array_sum(array_map(function($item) {return $item['west_ty_yest_sales'];},$dept_subcatg_descs)) . "</td>";
                    foreach($dept_subcatg_descs as $dept_subcatg_desc => $values) {
                                                echo "<tr>\n
                                                    <td style=\"padding-left: 4em;\">" . $dept_subcatg_desc . "</td>\n";
                                                $sum = $values['total_ty_yest_sales'];
                                                echo "<td>".$sum."</td>";
                                                $sum = $values['east_ty_yest_sales'];
                                                echo "<td>".$sum."</td>";
                                                $sum = $values['central_ty_yest_sales'];
                                                echo "<td>".$sum."</td>";
                                                $sum = $values['west_ty_yest_sales'];
                                                echo "<td>".$sum."</td>";
                    }
                }
            }
        }
    }

The commented out line is the problem for me now. This:

array_sum(array_map(function($item) {return $item['west_ty_yest_sales'];},$dept_subcatg_descs))

works fine at that level, but not at the higher levels. I have also tried to tweak this function to no avail:

function array_map_recursive($callback, $array) {
    foreach ($array as $key => $value) {
        if (is_array($array[$key])) {
            $array[$key] = array_map_recursive($callback, $array[$key]);
        }
        else {
            $array[$key] = call_user_func($callback, $array[$key]);
        }
    }
    return $array;
}

How can I make this work so that regardless of level it will dig down and sum the values for that portion of the array?

6
  • You are sure you callback is returning a value? there doesn't seem to be anything wrong with this recursive function. Commented Mar 5, 2014 at 17:11
  • If I use: array_sum(array_map_recursive(function($item) {return $item['total_ty_yest_sales'];},$dept_category_descs)) I get an illegal string offset error. The callback works here: array_sum(array_map(function($item) {return $item['total_ty_yest_sales'];},$dept_subcatg_descs)) Commented Mar 5, 2014 at 17:19
  • your passing an anonymous / lambda function as a string into your callback parameter, so call_user_func won't work like this, as it will try to call a function called function($item){...} you should define your callback separately, and pass the name of it in. Commented Mar 5, 2014 at 17:21
  • Thanks, I think I just caught on to that. Let's see if I can figure it out... Commented Mar 5, 2014 at 17:22
  • I think you probably can do it by replacing call_user_func($callback, $array[$key]); with simply $callback($array[$key]); Commented Mar 5, 2014 at 17:23

4 Answers 4

39
function array_map_recursive($callback, $array)
{
  $func = function ($item) use (&$func, &$callback) {
    return is_array($item) ? array_map($func, $item) : call_user_func($callback, $item);
  };

  return array_map($func, $array);
}
Sign up to request clarification or add additional context in comments.

4 Comments

Can you write a implementation?
Please specify what needs to be implemented?
if i give you an $array => ["a"=>1,"b"=>"2"] and if i want value of a+b then, how do i use it and what will be the code line for the function should i write $sum = array_map("array_map_recursive", $array) I want to exactly how do i use the function what is the $callback? Or should i just pass my own function in the place of callbace ? like function sum($p1,$p2){ return $p1+$p2;}
2
function array_map_recursive($callback, $array)
{
    if(is_array($callback)){
        foreach ($callback as $function){
            $array = array_map_recursive($function, $array);
        }
        return $array;
    }

    $func = function ($item) use (&$func, &$callback) {
        return is_array($item) ? array_map($func, $item) : call_user_func($callback, $item);
    };

    return array_map($func, $array);
}

This way you can call the function passing more functions.. ex:

$rowData = array_map_recursive(['utf8_decode', 'trim'], $rowData);

Or simple call just one:

$rowData = array_map_recursive('trim', $rowData);

Comments

1

It can be a little difficult if we add multiple arrays to the function. But with only one, there is no problem at all.

      function array_map_recursive(&$arr, $fn) {
            return array_map(function($item) use($fn){
                return is_array($item) ? array_map_recursive($item, $fn) : $fn($item);
            }, $arr);
        }

      $array = array_map_recursive($array, function($item){
            //TODO logic here
      });

Comments

1

filter_var can essentially be used to accomplish this

function array_map_recursive(callable $func, array $array) {
    return filter_var($array, FILTER_CALLBACK, ['options' => $func]);
}

There is one big drawback... The callback will receive the value as a string. and the leafs can't be objects

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.