0

I have an array to be summed by column(s)

Array (
    0 => [
        [category] => Tools, furniture & fixtures
        [period] => 2022-07
        [depreciation] => 100
    ],
    1 => [
        [category] => Tools, furniture & fixtures
        [period] => 2022-07
        [depreciation] => 50
    ],
    2 => [
        [category] => Machines
        [period] => 2022-07
        [depreciation] => 25
    ],
    3 => [
        [category] => Machines
        [period] => 2022-07
        [depreciation] => 75
    ],
    4 => [
        [category] => Machines
        [period] => 2022-08
        [depreciation] => 200
    ]
)

I want to sum depreciation column by combination of category and period column, something like :

Array (
    0 => [
        [category] => Tools, furniture & fixtures
        [period] => 2022-07
        [depreciation] => 150
    ],
    1 => [
        [category] => Machines
        [period] => 2022-07
        [depreciation] => 100
    ],
    2 => [
        [category] => Machines
        [period] => 2022-08
        [depreciation] => 200
    ]
)

I tried to used to utilize this function to do this IF only one column as the parameter/key, and no idea if it have to be more than one column (category and period) :

$itemsSummed = [];
foreach ($depreciations as $item) {
    if (array_key_exists($item['category'], $itemsSummed)) {
        $itemsSummed[$item['category']]['depreciation'] += $item['depreciation'];
    } else {
        $itemsSummed[$item['category']] = $item;
    }
}

$itemsSummed = array_values($itemsSummed);

How can i achieve this ?

3
  • I recommend use var_export() to export your array so that everyone can use it to reproduce and answer your problem. Commented Mar 27, 2022 at 13:48
  • This question is almost same with your question but need some more conditional. Commented Mar 27, 2022 at 13:51
  • @vee i've edited the question, it should more readable Commented Mar 27, 2022 at 13:53

2 Answers 2

2

The easiest way to do that is pooling the sums together based on unique keys, which in your case are concatenated from "category" and "period". First things first, your data:

$data = [
    0 => [
        'category' => 'Tools, furniture & fixtures',
        'period' => '2022-07',
        'depreciation' => '100'
    ],
    1 => [
        'category' => 'Tools, furniture & fixtures',
        'period' => '2022-07',
        'depreciation' => 50
    ],
    2 => [
        'category' => 'Machines',
        'period' => '2022-07',
        'depreciation' => 25
    ],
    3 => [
        'category' => 'Machines',
        'period' => '2022-07',
        'depreciation' => 75
    ],
    4 => [
        'category' => 'Machines',
        'period' => '2022-08',
        'depreciation' => '200'
    ]
];

Then let's iterate your data:

$sums = [];

foreach($data as $vals) {

    // Concatenate category+period for unique grouping key:
    $sum_key = "{$vals['category']}__{$vals['period']}";

    // Set sum to zero if not defined yet:
    $sums[$sum_key] ??= 0;

    // Add depreciation
    $sums[$sum_key] += $vals['depreciation'];
}

This would give you the following:

array(3) {
    ["Tools, furniture & fixtures__2022-07"] · int(150)
    ["Machines__2022-07"] · int(100)
    ["Machines__2022-08"] · int(200)
}

That's the basic logic. To model the output in the form of your source array, we'll follow the logic above with the difference that in place of ??= 0, we initialize the "sum" item with the values common to each group, and then add to the "depreciation" value at each iteration:

foreach($data as $vals) {

    // Concatenate category+period for unique grouping key:
    $sum_key = "{$vals['category']}__{$vals['period']}";
    
    // Initialize the grouped array item with zero "summable":
    $sums[$sum_key] ??= [
        'category' => $vals['category'],
        'period' => $vals['period'],
        'depreciation' => 0,
    ];
    
    // Add depreciation:
    $sums[$sum_key]['depreciation'] += $vals['depreciation'];
}

This would give you:

array(3) {
    ["Tools, furniture & fixtures__2022-07"] · array(3) {
        ["category"] · string(27) "Tools, furniture & fixtures"
        ["period"] · string(7) "2022-07"
        ["depreciation"] · int(150)
    }
    ["Machines__2022-07"] · array(3) {
        ["category"] · string(8) "Machines"
        ["period"] · string(7) "2022-07"
        ["depreciation"] · int(100)
    }
    ["Machines__2022-08"] · array(3) {
        ["category"] · string(8) "Machines"
        ["period"] · string(7) "2022-08"
        ["depreciation"] · int(200)
    }
}

If the grouping keys look awkward, or if you just want a numerically indexed array per your sample outcome, array_values($sums) in the end will "clean it up". I've left it as is to highlight the logic of using a "unique grouping key" to aggregate values.

Sign up to request clarification or add additional context in comments.

Comments

1
$list = [
    [ 'category' => 'Tools', 'period' => '2022 - 07', 'depreciation' => 100 ],
    [ 'category' => 'Tools', 'period' => '2022 - 07', 'depreciation' => 50 ],
    [ 'category' => 'Machines', 'period' => '2022 - 07', 'depreciation' => 25 ],
    [ 'category' => 'Machines', 'period' => '2022 - 07', 'depreciation' => 75 ],
    [ 'category' => 'Machines', 'period' => '2022 - 08', 'depreciation' => 200 ]
];

$result = array_reduce(
    $list,
    function ($carry, $item) {
      foreach ($carry as &$value) {
        if ($value['category'] === $item['category'] && $value['period'] === $item['period']) {
          $value['depreciation'] += $item['depreciation'];
          return $carry;
        }
      }
      return [ ...$carry, $item ];
    },
    []
);

print_r($result);

2 Comments

A bit of legend as to why and how this works would make your fine solution educational. As it is, people are likely to "copy magic" from the above.
Thanks @lukas.j, cool answer, i need to dig it deeper tho , but thanks, this also solved my problems

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.