Jump to content

Array of objects with nested objects


bjesltomvi

Recommended Posts

Hello,

I have an array that I want to transfer it into another format. The array look like:

        $data = [
            [
                "id"=>1,
                "type"=>"title",
                "data"=> "Title goes here"
            ],
            [
                "id"=>2,
                "type"=>"repeat",
                "number"=>3,
            ],
            [
                "id"=>3,
                "type"=>"media",
                "data"=> "path to media"
            ],
            [
                "id"=>4,
                "type"=>"close_repeat"
            ],
            [
                "id"=>5,
                "type"=>"repeat",
                "number"=>3,
            ],
            [
                "id"=>6,
                "type"=>"title",
                "data"=> "Title goes here"
            ],
            [
                "id"=>7,
                "type"=>"repeat",
                "number"=>2,
            ],
            [
                "id"=>8,
                "type"=>"text",
                "data"=> "Text goes here"
            ],
            [
                "id"=>9,
                "type"=>"close_repeat"
            ],
            [
                "id"=>10,
                "type"=>"close_repeat"
            ],
            [
                "id"=>11,
                "type"=>"cover",
                "data"=> "Cover data goes here"
            ],
        ];

And I want to transform it into:

{
    "0": [
        {
            "id": 1,
            "type": "title",
            "data": "Title goes here"
        }
    ],
    "1": [
        {
            "id": 3,
            "type": "media",
            "data": "path to media"
        },
        {
            "id": 3,
            "type": "media",
            "data": "path to media"
        },
        {
            "id": 3,
            "type": "media",
            "data": "path to media"
        }
    ],
    "2":[
        {
            "id": 6,
            "type": "title",
            "data": "Title goes here"
        },
        {
            "id": 8,
            "type": "text",
            "data": "Text goes here"
        },
        {
            "id": 8,
            "type": "text",
            "data": "Text goes here"
        }
    ],
    "3":[
        {
            "id": 6,
            "type": "title",
            "data": "Title goes here"
        },
        {
            "id": 8,
            "type": "text",
            "data": "Text goes here"
        },
        {
            "id": 8,
            "type": "text",
            "data": "Text goes here"
        }
    ],
    "4":[
        {
            "id": 6,
            "type": "title",
            "data": "Title goes here"
        },
        {
            "id": 8,
            "type": "text",
            "data": "Text goes here"
        },
        {
            "id": 8,
            "type": "text",
            "data": "Text goes here"
        }
    ],
    "5": [
        {
            "id": 11,
            "type": "cover",
            "data": "Cover data goes here"
        }
    ]
}

 

The idea is that each object can appear once or multiple times. If an object comes between objects of type repeat and close_repeat then it should be repeated based on number:x. The problem is when the repeat is nested as in id=5 to id=10. Here it should be that id=6 appear once with two repeated id=8. But in total, this whole id=6 and id=8 (twice) should appear three times since the repetition at id=5 is 3. I hope this is clear. I tried using loops:

 

    public function dataTraversLoop($data, &$newData, $i){
        $dataCount = count($data);
        if($i>=$dataCount){
            return;
        }
        $objectIndex=0;
        for(;$i<$dataCount;$i++){
            if($data[$i]['type']=='repeat'){
                $objectIndex++;
                $repeat = $data[$i]['number'];
                $i++;
                
                for($j=0;$j<$repeat;$j++){

                    $tmpData = $data[$i];
                    $newData [$objectIndex][$j] = $tmpData;
                }
            }
            else if($data[$i]['type']=='close_repeat'){
                $i++;
                $objectIndex++;
            }
            else{
                $tmpData = $data[$i];
                $newData [$objectIndex][] = $tmpData;
            }
        }
    }

And also recursion:

 

    public function dataTravers($data, &$newData, &$repeat, $i, $objectIndex){
        $dataCount = count($data);
    
        for( ; $i<$dataCount; $i++){
    
            if($data[$i]['type']=='repeat'){
                $repeat = $repeat * $data[$i]['number'];
                return $this->dataTravers($data, $newData, $repeat, $i+1, $objectIndex);
            }
    
            if($data[$i]['type']=='close_repeat'){
                $repeat = 1;
                return $this->dataTravers($data, $newData, $repeat, $i+1, $objectIndex+1);
            }
    
            if($i >= $dataCount){
                return $newData;
            }
    
            $tmpData = $data[$i];
            $newData [$objectIndex][] = $tmpData;

            return $this->dataTravers($data, $newData, $repeat, $i+1, $objectIndex);
            $objectIndex++;
    
        }

 

Link to comment
Share on other sites

This looks like homework ....

I understand the idea, and it smells like a recursive exercise, which teachers love, and yet are rarely employed due to the huge overhead involved in building a functional stack.

2 things here:

  1. You have code that "looks" ok.  Obviously you are having some problems with it, but you have no examples or debugging of what doesn't work
  2. Do you expect us to set up an environment and run your code and debug it for you?  See #1.  

So in general, yes, I would say that yes, if this is an assignment, this is an exercise that should involve recursion.    

This code looks very suspect for a few reasons including that repeat is not shown to be initialized anywhere, and it should be local to the running function on the stack:

 $repeat = $repeat * $data[$i]['number'];

 

Just off a quick browse of your code, you are trying to combine the reading of the array with the processing of a repeat/close_repeat.  You want a recursive function that only handles the repeat/close cycle.

So what you need in terms of variables is:

  • index of global array
  • temporary array built, which is return when function completes and is returned to be added to the finalized array.  

Inside your recursive function you can encounter 1 of 3 things:

  • An entry which you add to your temporary array
  • A repeat, where you calls the function recursively having advanced the start/end index
  • an end_repeat where you duplicate the temp index the #repeat times and return it
    • you increment the index internally, so you need to pass this by reference

 

One trap you probably have is trying to control the other process with a for loop.  What you actually want is a repeat--until pattern where you will process starting with index=0 until the index = count(array) -1.    PHP does not have repeat/until but it does have do..while, so that is what your control should be based on.

Hopefully this leads you to a solution, otherwise, again we need specific code, with your debugging and specific problems you are having with select sections of the code.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.