0

I have an array of objects that looks like this:

Array
(
    [0] => stdClass Object
        (
            [ContractorID] => 7049             //<- REMOVE
            [ContractorName] => Supermarket 1  //<-REMOVE
            [SpendAmount] => 615.36            //<-SUM OF ALL ELEMENTS WHERE GroupID IS THE SAME
            [BonusAmount] => 24.61             //<-SUM OF ALL ELEMENTS WHERE GroupID IS THE SAME
            [GroupID] => 1                     //<- RETAIN
            [GroupDescription] => Supermarkets //<- RETAIN
        )

    [1] => stdClass Object
        (
            [ContractorID] => 11233
            [ContractorName] => Supermarket 2
            [SpendAmount] => 858.74
            [BonusAmount] => 34.35
            [GroupID] => 1
            [GroupDescription] => Supermarkets
        )

    [2] => stdClass Object
        (
            [ContractorID] => 19393
            [ContractorName] => Car repair shop 1 
            [SpendAmount] => 386.79
            [BonusAmount] => 15.47
            [GroupID] => 2
            [GroupDescription] => Automotive
        )

    [3] => stdClass Object
        (
            [ContractorID] => 19868
            [ContractorName] => Mike's Autos
            [SpendAmount] => 364.81
            [BonusAmount] => 14.59
            [GroupID] => 2
            [GroupDescription] => Automotive
        )

 )   

I want to end up with an array that looks like this:

[0] => stdClass Object
        (
            [SpendAmount] => 1474.1
            [BonusAmount] => 58.96
            [GroupID] => 1
            [GroupDescription] => Supermarkets
        )

    [1] => stdClass Object
        (
            [SpendAmount] => 751.6
            [BonusAmount] => 30.06
            [GroupID] => 2
            [GroupDescription] => Automotive
        )
)

Where BonusAmount is the total of all elements BonusAmount and SpendAmount is the total of all elements SpendAmount.

The summing is simple enough in and of itself, but what I am struggling with is how to retain the GroupID and GroupDescription as I loop through the elements.

Could anyone give me an idea of how I should "retain" the GroupID and GroupDescription syntactically and create an element in my resultant array based on the GroupID? All help much appreciated.

4
  • 1
    Someone needs to read manuals. Commented Jun 14, 2017 at 13:23
  • @u_mulder Is that your contribution to an honest question? Commented Jun 14, 2017 at 13:27
  • @j your question Could anyone give me an idea. My idea - read a manual. Commented Jun 14, 2017 at 13:29
  • 1
    @u_mulder Congratz. You win the Sheldon Cooper award. Commented Jun 14, 2017 at 13:32

4 Answers 4

2

One way of solving this would be to loop through the array of objects checking which ones you've already had and which ones you haven't yet. An example of how to do this is as followed:

        $results = [];
        foreach($objects as $object){
            if(isset($results[$object->GroupID])){
                $results[$object->GroupID]->SpendAmount += $object->SpendAmount;
                $results[$object->GroupID]->BonusAmount += $object->BonusAmount;
            }else{
                $results[$object->GroupID] = [
                    'SpendAmount' => $object->SpendAmount,
                    'BonusAmount' => $object->BonusAmount,
                    'GroupDescription' => $object->GroupDescription
                ];
            }
        }
Sign up to request clarification or add additional context in comments.

Comments

2

You can traverse the array and sum the items, live demo.

 $r = [];
 foreach($array as $v)
 {
 @$r[$v->GroupID]->SpendAmount += $v->SpendAmount;
 @$r[$v->GroupID]->BonusAmount += $v->BonusAmount;
 @$r[$v->GroupID]->GroupID = $v->GroupID;
 @$r[$v->GroupID]->GroupDescription = $v->GroupDescription;
 }
 print_r(array_values($r));

Comments

1

I've used array_walk_recursive, but array_walk or even a simple foreach would suffice.

//Recreate input data from question
$in = [
        (object) [
            'ContractorID' => '7049',
            'ContractorName' => 'Supermarket 1',
            'SpendAmount' => '615.36',
            'BonusAmount' => '24.61',
            'GroupID' => '1',
            'GroupDescription' => 'Supermarkets',
        ],
        (object) [
            'ContractorID' => '11233',
            'ContractorName' => 'Supermarket 2',
            'SpendAmount' => '858.74',
            'BonusAmount' => '34.35',
            'GroupID' => '1',
            'GroupDescription' => 'Supermarkets',
        ],
        (object) [
            'ContractorID' => '19393',
            'ContractorName' => 'Car repair shop 1 ',
            'SpendAmount' => '386.79',
            'BonusAmount' => '15.47',
            'GroupID' => '2',
            'GroupDescription' => 'Automotive',
        ],
        (object) [
            'ContractorID' => '19868',
            'ContractorName' => 'Mike\'s Autos',
            'SpendAmount' => '364.81',
            'BonusAmount' => '14.59',
            'GroupID' => '2',
            'GroupDescription' => 'Automotive',
        ]
];

//For each object in the array $in, add the object details to a new array.
$return = [];
array_walk_recursive($in, function($a) use (&$return) {
    $found = false;
    //Does this group exist in the array? If so - add spendamount and bonus amount to group.
    foreach($return as $group) {
        if($group->GroupID== $a->GroupID) {
            $found = true;

            $group->SpendAmount += $a->SpendAmount;
            $group->BonusAmount += $a->BonusAmount;

            break;
        }
    }

    //Group not found - create it.
    if(!$found) {
        $return[] = (object) [
            'SpendAmount' => $a->SpendAmount,
            'BonusAmount' => $a->BonusAmount,
            'GroupID' => $a->GroupID,
            'GroupDescription' => $a->GroupDescription,
        ];
    }
});

var_dump($return);
/*
array (size=2)
  0 => 
    object(stdClass)[6]
      public 'SpendAmount' => float 1474.1
      public 'BonusAmount' => float 58.96
      public 'GroupID' => string '1' (length=1)
      public 'GroupDescription' => string 'Supermarkets' (length=12)
  1 => 
    object(stdClass)[7]
      public 'SpendAmount' => float 751.6
      public 'BonusAmount' => float 30.06
      public 'GroupID' => string '2' (length=1)
      public 'GroupDescription' => string 'Automotive' (length=10)
*/

2 Comments

Thank you kindly, sir. I will attempt this and let you know what happens.
This works perfectly, AND I learned something. Thank you so much.
0

That is not an array but an object and hence they are treated differently http://php.net/manual/en/language.types.object.php

You access object by $obj->field_name

and you can loop through the object as such

$result = [];
foreach($object as $obj) {
   $result[] = $obj->field1 + $ojb->field2;
}

1 Comment

Actually, it is an array of objects. The question pertains to how to "flatten" the array based on certain keys in the object, whilst retaining a sum of certain values.

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.