php - Calculate totals for each column of a two dimensional array (matrix)

597

Given the array below, how can I create a sum array with matching keys?

$arr = [
    ['alpha', 1, 2, 3, 4, 5],
    ['beta', 1, 2, 3, 4, 5],
    ['gamma', 1, 2, 3, 4, 5],
    ['delta', 1, 2, 3, 4, 5]
];

This is what I eventually want:

['', 4, 8, 12, 16, 20]

Is this the most efficient way?

function getArrTotals($arr) {
    $arrTotal = array();
    foreach ($arr as $subArr) {
        foreach ($subArr as $k => $v) {
            if (is_numeric($v)) {
                if (!array_key_exists($k,$arrTotal)) {
                    $arrTotal[$k] = 0;
                }
                $arrTotal[$k] = $arrTotal[$k] + $v;
            } else {
                if (!array_key_exists($k,$arrTotal)) {
                    $arrTotal[$k] = '';
                }
            }
        }
    }
    return $arrTotal;
}
118

Answer

Solution:

Using the new array_column() function of PHP 5.5:

$colCount = count($arr[0]);
$result = array();
for ($i = 0; $i < $colCount; $i++) {
    $result[] = 
        array_sum(
        array_column($arr, $i)
    );
}
var_dump($result);

or for earlier versions of PHP

$result = array();
foreach(call_user_func_array('array_map',array_merge(array(NULL),$arr)) as $column) {
    $result[] = array_sum($column);
}
var_dump($result);

Both methods assume the same number of entries in each sub-array

EDIT

Filtering out the non numeric values to return an empty string for the first column:

$colCount = count($arr[0]);
$result = array();
for ($i = 0; $i < $colCount; $i++) {
    $values = array_filter(
        array_column($arr, $i),
        'is_numeric'
    );
    $result[] = count($values) > 0 ? array_sum($values) : '';
}
var_dump($result);

and

$result = array();
foreach(call_user_func_array('array_map',array_merge(array(NULL),$arr)) as $column) {
    $values = array_filter($column,
        'is_numeric'
    );
    $result[] = count($values) > 0 ? array_sum($values) : '';
}
var_dump($result);

If you want a null instead, then simply replace the '' with null

260

Answer

Solution:

You only need to "transpose" the data (access columns of data as rows) then sum each subset.array_map(callback_function, ...$array) does the transposition. Then...$col collects the parameters (of indeterminant length) as a single array of data. Finally,array_sum() sums the subset of data.

Code: (Demo)

$arr = [
    ['alpha', 1, 2, 3, 4, 5],
    ['beta', 1, 2, 3, 4, 5],
    ['gamma', 1, 2, 3, 4, 5],
    ['delta', 1, 2, 3, 4, 5]
];
       
var_export(
    array_map(fn(...$col) => array_sum($col), ...$arr)
);

Output:

array (
  0 => 0,
  1 => 4,
  2 => 8,
  3 => 12,
  4 => 16,
  5 => 20,
)

If you adamantly want an empty string for the first column's total, you can write a condition in the callback. (Demo)

var_export(
    array_map(
        fn(...$col) =>
            is_numeric($col[0])
                ? array_sum($col)
                : '',
        ...$arr
    )
);

People are also looking for solutions to the problem: php - range of numbers from array

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.