1

Currently, this is my code, but it doesn't work:

//$queryBalance is the array received from an sql select
foreach ($queryBalance as $index => $runrows){ 
    $val = $runrows->balance;
    $val = str_ireplace(".","",$val);
    $val = str_ireplace(",",".",$val);
    //echo($i.' - '.$runrows->id_month.' ; ');
    //$valor = $runrows->id_month == $i ? $val : 'Null';
    if($i > $monthFim){
        $i = $monthInicio-1;
        array_push($balanceArray, $balanceTeste);                     
        echo('('.$i.' - '.$runrows->id_month.'); ');
        //dd('('.$balanceArray.' - '.$balanceTeste.'); ');
    }else{
        array_push($balanceTeste, $valor);
    }
    $i++; 
}

I want to transform this input array ($queryBalance):

array:6 [
   0 => {
    "balance": "-257,21"
    "id_month": 1
    "year": "2018"
  }
  1 => {
    "balance": "-257,21"
    "id_month": 2
    "year": "2018"
  }
  2 => {
    "balance": "0"
    "id_month": 1
    "year": "2018"
  }
  3 => {
    "balance": "0"
    "id_month": 2
    "year": "2018"
  }
  4 => {
    "balance": "-64609,14"
    "id_month": 1
    "year": "2018"
  }
  5 => {
    "balance": "-64609,14"
    "id_month": 2
    "year": "2018"
  }
]

into this (the indexes name is irrelevant, I put it there to exemplify the logic):

array:3 [
   0 => {
    "balance_month1_year2018": "-257,21"
    "balance_month2_year2018": "-257,21"
  }
  1 => {
    "balance_month1_year2018": "0"
    "balance_month2_year2018": "0"
  }
  2 => {
    "balance_month1_year2018": "-64609,14"
    "balance_month2_year2018": "-64609,14"
  }
]

Basically, I want group by year and month to get the balances.

ps: The data will always be ordered

1 Answer 1

1
  1. Generate an array of unique year and month combinations.
    (*Declare as keys to ensure that they are unique).

  2. Iterate $queryBalance until is empty/exhausted.
    (*If you need to re-use the original $queryBalance make a copy.)

  3. Assign the first subarray of $queryBalance as a variable for the next line.

  4. If expected date pair from $uniques is same as $first date pair, remove the first subarray (via array_shift()) and store the balance; otherwise store NULL and do not modify $queryBalance.

  5. $temp is a "batching" array. When the foreach loop is finished, the batch is ready to transfer to $result.

Code: (Demo)

$queryBalance=[
    (object)["balance"=>"-257,21","id_month"=>12,"year"=>"2017"],
    (object)["balance"=>"-257,21","id_month"=>1,"year"=>"2018"],
    (object)["balance"=>"-257,21","id_month"=>2,"year"=>"2018"],
    (object)["balance"=>"166,66","id_month"=>3,"year"=>"2018"],
    (object)["balance"=>"55","id_month"=>12,"year"=>"2017"],
    //(object)["balance"=>"0","id_month"=>1,"year"=>"2018"],
    (object)["balance"=>"0","id_month"=>2,"year"=>"2018"],
    (object)["balance"=>"55","id_month"=>3,"year"=>"2018"],
    (object)["balance"=>"-22257,21","id_month"=>12,"year"=>"2017"],
    (object)["balance"=>"-64609,14","id_month"=>1,"year"=>"2018"],
    (object)["balance"=>"-64609,14","id_month"=>2,"year"=>"2018"],
    (object)["balance"=>"-12234,89","id_month"=>3,"year"=>"2018"]
];
foreach($queryBalance as $row){
    $uniques[$row->year.'-'.$row->id_month]=NULL;  // determine all unique date groups
}

while($queryBalance){
    $temp=[];
    foreach($uniques as $date=>$null){
        $first=current($queryBalance);  // cache the element that is currently first in $queryBalance
        $temp[]=($date==$first->year.'-'.$first->id_month) ? array_shift($queryBalance)->balance : NULL;  // extract from array, or store NULL without modifying $queryBalance
    }
    $result[]=$temp;
}

var_export($result);

Output:

array (
  0 => 
  array (
    0 => '-257,21',
    1 => '-257,21',
    2 => '-257,21',
    3 => '166,66',
  ),
  1 => 
  array (
    0 => '55',
    1 => NULL,
    2 => '0',
    3 => '55',
  ),
  2 => 
  array (
    0 => '-22257,21',
    1 => '-64609,14',
    2 => '-64609,14',
    3 => '-12234,89',
  ),
)
Sign up to request clarification or add additional context in comments.

1 Comment

My second method should be better suited for your task then. 3v4l.org/5HquC

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.