2

What I have

So I have a variable named result that is formatted like this:

Array
(
[0] => stdClass Object
    (
        [description] => dev1
        [id] => 09A
        [sum] => 52
        [completed_pct_completed] => 97.97
        [completed_pct_1msec] => 11.44
        ....
    )

[1] => stdClass Object
    (
        [description] => dev1
        [id] => 273
        [sum] => 59
        [completed_pct_completed] => 94.43
        [completed_pct_1msec] => 10.95
        ....
    )

[2] => stdClass Object
    (
        [description] => dev1.1
        [id] => 28A
        [sum] => 39
        [completed_pct_completed] => 95.55
        [completed_pct_1msec] => 20.78
        ....
    )
[3] => stdClass Object
    (
        [description] => dev1.1
        [id] => 28B
        [sum] => 31
        [completed_pct_completed] => 91.55
        [completed_pct_1msec] => 28.78
        ....
    )
....

There are about 250 different objects. The problem with this current order is that the description of each becomes redundant to the point that I just one want to put all the data of each description into an object. Descriptions go by dev1.x, where x can be a different number or letter or whatever, doesn't matter.

What I want to do:

I'm trying to reorder $result into the format below. Pretty much, by traversing each item in the $result array, each description in result will be it's own property in a new object. Inside of each description property will be subitems like id, sum, completed_pct_completed, etc. It will look like this:

stdClass Object
(
[dev1] => stdClass Object
    (
        [id] => Array
            (
                [0] => 182
                [1] => 218
                [2] => 218
                [3] => 021
                [4] => 186
                [5] => 287
                [6] => 21A
            )

        [sum] => Array
            (
                [0] => 567
                [1] => 567
                [2] => 567
                [3] => 567
                [4] => 567
                [5] => 567
                [6] => 567
            )
        [completed_pct_completed] => Array
            (
                [0] => 567
                [1] => 567
                [2] => 567
                [3] => 567
                [4] => 567
                [5] => 567
                [6] => 567
            )
        [completed_pct_1msec] => Array
            (
                [0] => 567
                [1] => 567
                [2] => 567
                [3] => 567
                [4] => 567
                [5] => 567
                [6] => 567
            )
            .........

    )

[dev1.1] => stdClass Object
    (
        [id] => Array
            (
                [0] => 182
                [1] => 329
                [2] => 465
                [3] => 685
                [4] => 686
                [5] => 607
                [6] => 61A
            )

        [sum] => Array
            (
                [0] => 567
                [1] => 567
                [2] => 567
                [3] => 567
                [4] => 567
                [5] => 567
                [6] => 567
            )
        [completed_pct_completed] => Array
            (
                [0] => 567
                [1] => 567
                [2] => 567
                [3] => 567
                [4] => 567
                [5] => 567
                [6] => 567
            )
        [completed_pct_1msec] => Array
            (
                [0] => 567
                [1] => 567
                [2] => 567
                [3] => 567
                [4] => 567
                [5] => 567
                [6] => 567
            )
         ............
       )
       ............

What I've done so far

So here's how I've constructed what I want so far:

I made an object with properties of each unique description:

$object = new STDClass();
//$flipped is the transposed version of $result, then I got unique names
foreach (array_unique($flipped['description']) as $string)
    $object->{$string} = array();

This went perfectly fine. Then, I added the subitems to each description property in $object

$dummyObject = new STDClass();
foreach ($object as $objectKey=>$objectValue) {
    foreach ($result[0] as $key=>$value){
        if ($key!='description'){
            $dummyObject->{$key}=array();
            $object->$objectKey=$dummyObject;
        }
    }
}

This also went fine.

The problem here is inserting the data into each id and summary, etc.. Here's what I've done:

//add data to the subitems
//foreach dev1.x => array
foreach ($object as $key => $nextObject)
{
    //foreach array as subitems(id, board, etc.) => array
    foreach ($nextObject as $nextKey => $dataArray)
    {
        $dummyArray = array();
        foreach ($result as $array)
        {
            foreach ($array as $arrayKey => $arrayValue)
            {
                if ($array->{'description'} == $key) {
                    if ($nextKey == $arrayKey) {
                        $dummyArray[]=$arrayValue;
                    }
                }
            }
        }
        $object->{$key}->{$nextKey} = $dummyArray;
    }
}

In the end, all the data from the last dev1.x property ends up being overwritten into every single dev1.x property. I've tried adding break; in multiple places hoping that I'd be able to deduce what is going wrong. I have a gut feeling that there's more going on than I know with the foreach statements. Would anyone mind helping me with this?

Thanks

3
  • based on input values what expected outcome you want? Aslo add some more values to input an address them too in the expected outcome. Commented Oct 3, 2016 at 20:05
  • @Anant, I added more. Is this sufficient? Commented Oct 3, 2016 at 20:13
  • No. You didn't say where/how $result[0] is populated from. Since I doubt you're defining the object in code, it means you are extracting it from a database. In which case the right solution is to populate it into the structure you need at the point where it comes out of the database - not the wrong structure and then converting it. Fix the right problem. Commented Oct 3, 2016 at 20:36

2 Answers 2

1

It looks like it may be less complicated than it seems. Unless I'm misunderstanding what the transformation should be, you can do it like this:

foreach ($result as $obj) {
    foreach ($obj as $key => $value) {
        if ($key != 'description') {
            $new_result->{$obj->description}->$key[] = $value;
        }
    }
}

This should create the object and add the appropriate properties and values all at once.

The reason you're getting the duplication is in this part:

$dummyObject = new STDClass();
foreach ($object as $objectKey=>$objectValue) {
    foreach ($result[0] as $key=>$value){
        if ($key!='description'){
            $dummyObject->{$key}=array();
            $object->$objectKey=$dummyObject;
        }
    }
}

When you do $object->$objectKey=$dummyObject; because you created the object before the loop, you're resetting and reassigning the same object to each $objectKey. So when you fill it with values later, you just end up with multiple copies of whatever the last one was. If you use a copy of the object insteady ($object->$objectKey= clone $dummyObject;) it should work. But it does seem a bit overcomplicated.

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

Comments

0

Just create keys while iterating:

$data = new stdClass();
foreach ($result as $object) {
    $description = $object->description;
    isset($data->{$description}) or $data->{$description} = new stdClass();

    foreach ($object as $name => $value) {
        if ($name === 'description') { continue; }
        $data->{$description}->{$name}[] = $value;
    }
}

I don't like descriptions as field names though. Access to $data->{'dev1.1'} is ugly. Would pack it into an array of objects, but description property would be just a string and other properties would be aggregated arrays. It would need some changes in procedure (index of descriptions propably).

Comments

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.