3

I have an array with some values. Here I need to make a calculation for Year 2019 only.

$array = array(
                "date_2019_12" => 0,
                "date_2019_11" => 0,
                "date_2019_10" => 0,
                "date_2019_09" => 0,
                "date_2019_08" => 0,
                "date_2019_07" => 0,
                "date_2019_06" => 0,
                "date_2019_05" => 0,
                "date_2019_04" => 0,
                "date_2019_03" => 0,
                "date_2019_02" => 0,
                "date_2019_01" => 10,
                "date_2018_12" => 1,
                "date_2018_11" => 2,
                "date_2018_10" => 3,
                "date_2018_09" => 4,
                "date_2018_08" => 5,
                "date_2018_07" => 6,
        );

        krsort($array);

From this array, I need to calculate the sum of previous five months & current month starting "date_2019_01".

That means I need final array result like below:

"date_2019_01" => 25(10+1+2+3+4+5)
"date_2019_02" => 20(0+10+1+2+3+4)
"date_2019_03" => 16(0+0+10+1+2+3)
"date_2019_04" => 13(0+0+0+10+1+2)
... until "date_2019-12".

I have spend many times finding solution but I could not. Can anybody help me?

I have tried following code and somewhere now I am lost.

$newArr = array();
        foreach($array as $key => $val) {
            $explode = explode("_", $key);
            $value = (int)$explode[2];
            for($i = 0; $i <= 5; $i++) {
                $newArr[$array[$explode[0].'_'.$explode[1].'_'.$value]] = $array[$explode[0].'_'.$explode[1].'_'.$value];
                $value--;
            }
        }
2

This code will do what you want. It uses a nested loop to iterate over each month and the 5 preceding months, creating a sum for each one from the different date values in the array:

$year = 2019;
$sums = array();
for ($i = 1; $i <= 12; $i++) {
    $sum = 0;
    for ($j = $i - 5; $j <= $i; $j++) {
        $y = $year;
        $m = $j;
        if ($m <= 0) {
            $m += 12;
            $y -= 1;
        }
        $date = sprintf("date_%4d_%02d", $y, $m);
        $sum += $array[$date];
    }
    $date = sprintf("date_%4d_%02d", $year, $i);
    $sums[$date] = $sum;
}
print_r($sums);

Output:

Array (
  [date_2019_01] => 25
  [date_2019_02] => 20
  [date_2019_03] => 16
  [date_2019_04] => 13
  [date_2019_05] => 11
  [date_2019_06] => 10
  [date_2019_07] => 0
  [date_2019_08] => 0
  [date_2019_09] => 0
  [date_2019_10] => 0
  [date_2019_11] => 0
  [date_2019_12] => 0 
)

Demo on 3v4l.org

3

You don't need to nest the loops, you can use one loop, array_slice and array_sum.

krsort($array);

$year = "2019";
$keys = array_keys($array); //save keys since we use array_values in the loop
foreach(array_values($array) as $k => $v){
    // If the year is found in the key slice out the next six item and sum them
    if(strpos($keys[$k], $year) !== false) $res[$keys[$k]] = array_sum(array_slice($array, $k, 6)); 
}
var_dump($res);

https://3v4l.org/LSQRg

  • You should adapt your code to show 2018 values as well. – Andrei Lupuleasa Apr 19 at 8:03
  • 1
    @AndreiLupuleasa OP only wanted data for 2019 – Nick Apr 19 at 8:06
  • As Nick says, OP wants to be able to select year (I believe). – Andreas Apr 19 at 8:12
  • Fair enough but your code wont work in 2020 because your using magic numbers. Anyway nice solution array_sum is fater than foreach and better to use. – Andrei Lupuleasa Apr 19 at 8:13
  • @AndreiLupuleasa why wouldn't my code work in 2020? What magic number? – Andreas Apr 19 at 8:33
2

Use: https://3v4l.org/7AYfT

        $newArr = array();
        foreach($array as $key => $val) {
            $i=1;
            $newArr[$key] = $val;
            foreach($array as $key2 => $val2){
                if($key>$key2 && $i <= 5){
                    $newArr[$key] += $val2;
                    $i++;
                }
            }
        }

array(18) {
  ["date_2019_12"]=>
  int(0)
  ["date_2019_11"]=>
  int(0)
  ["date_2019_10"]=>
  int(0)
  ["date_2019_09"]=>
  int(0)
  ["date_2019_08"]=>
  int(0)
  ["date_2019_07"]=>
  int(0)
  ["date_2019_06"]=>
  int(10)
  ["date_2019_05"]=>
  int(11)
  ["date_2019_04"]=>
  int(13)
  ["date_2019_03"]=>
  int(16)
  ["date_2019_02"]=>
  int(20)
  ["date_2019_01"]=>
  int(25)
  ["date_2018_12"]=>
  int(21)
  ["date_2018_11"]=>
  int(20)
  ["date_2018_10"]=>
  int(18)
  ["date_2018_09"]=>
  int(15)
  ["date_2018_08"]=>
  int(11)
  ["date_2018_07"]=>
  int(6)
}
2

There are two steps I have performed.

Step 1: Sorting custom format array by keys

// sort the array first by date of given format
uksort($array, function ($a, $b) {
    $t1 = strtotime(str_replace(["date_", "_"], ["", "-"], $a) . '-01');
    $t2 = strtotime(str_replace(["date_", "_"], ["", "-"], $b) . '-01');
    return $t1 - $t2;
});

Step 2: Main logic to given condition with inline documentation

$flag   = false;
$result = [];
foreach ($array as $key => $value) {
    if ($key != 'date_2019_01' && !$flag) {
        continue; // check until 'date_2019_01' wont come
    } else {
        $flag   = true; // set the flag and skip above condition
        $curKey = array_search($key, array_keys($array), true); // get integer index of date_2019_01
        if ($key !== false) { // if key exists
            $slice        = array_slice($array, $curKey - 5, 6, true); // from current index last 5(6-5, 7-5,8-5,....) to 6(including current element)
            $result[$key] = array_sum($slice); // sum of there values
        }
    }
}

Brief of things I have used to make it clear for understanding of applications of it.

uksort — Sort an array by keys using a user-defined comparison function
array_keys — Return all the keys or a subset of the keys of an array
array_search — Searches the array for a given value and returns the first corresponding key if successful
array_slice — Extract a slice of the array
array_sum — Calculate the sum of values in an array
str_replace — Replace all occurrences of the search string with the replacement string

  • 1
    that was a very good explanation. Thank You. – S S Apr 19 at 10:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.