2
\$\begingroup\$

Below is a snippet that uses array_reduce() to calculate totals from a detailed dataset. The data shown is representative of a larger dataset.

This code outputs the expected results. I'm seeking some peer input on how this array_reduce() is written because this is my first time using it in PHP. I'm more familiar with JavaScript .reduce() function. Is there a more concise way to write this?

<?php
$data = [
    'header' => [
        'customerId' => 28449,
        'locationId' => 1278,
        'orderId' => 764,
        'orderDate' => '2022-02-01'
    ],
    'detail' => [
        '0' => [
            'itemId' => 210711,
            'orderQuantity' => 10,
            'fillQuantity' => 8,
            'unitPrice' => 120.54
        ],
        '1' => [
            'itemId' => 582284,
            'orderQuantity' => 151,
            'fillQuantity' => 144,
            'unitPrice' => 85.68
        ],
        '2' => [
            'itemId' => 476537,
            'orderQuantity' => 87,
            'fillQuantity' => 87,
            'unitPrice' => 25.75
        ]
    ]
];

$initialValues = array_fill_keys(['itemCount', 'orderQuantity', 'fillQuantity'], 0);
$totals = [];
$totals = array_reduce($data['detail'], function ($result, $item) {
    $result['itemCount']++;
    $result['orderQuantity'] += $item['orderQuantity'];
    $result['fillQuantity'] += $item['fillQuantity'];
    return $result;
}, $initialValues);


echo '<pre>' . print_r(['data' => $data, 'totals' => $totals], 1) . '</pre>';
?>

Here is the 'totals' output, which is correct:

[totals] => Array
    (
         [itemCount] => 3
         [orderQuantity] => 248
         [fillQuantity] => 239
    )
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I don't see anything to improve inside the callback body.

I do prefer to eliminate single-only variable declarations unless the declaration improves readability or breaks up excessively wide lines of code.

From PHP7.4, concise "arrow function syntax" (fn() => ...) is available, but it cannot be used with array_reduce() because the syntax does not allow multiline bodies. (Although there is a proposal to accommodate multiline bodies with less syntax -- PHP RFC: Auto-capturing multi-statement closures)

If you are going to write function parameters on multiple lines, then write all parameters on separate lines for easier (human) reading.

Declaring $total as an empty array then immediately and unconditionally overwriting it is not needed -- just omit the empty declaration.

Suggested code:

$totals = array_reduce(
    $data['detail'],
    function ($result, $item) {
        ++$result['itemCount'];
        $result['orderQuantity'] += $item['orderQuantity'];
        $result['fillQuantity'] += $item['fillQuantity'];
        return $result;
    },
    array_fill_keys(['itemCount', 'orderQuantity', 'fillQuantity'], 0)
);
\$\endgroup\$
2
  • \$\begingroup\$ What is the reason for recommending ++$result['itemCount']; rather than using $result['itemCount']++;? \$\endgroup\$ Commented Feb 13, 2022 at 19:21
  • 2
    \$\begingroup\$ Pre-incrementation is a personal preference -- which is why I didn't bullet point that change. I've read that pre-incrementation is slightly faster than post-incrementation, so by default, I choose this style. I doubt it makes any difference in any of the scripts that I've written. \$\endgroup\$ Commented Feb 13, 2022 at 19:25

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.