Kvvaradha
Kvvaradha

Reputation: 852

How to create sub arrays with help of parent id

Here is my collected array.

$raw_ar = Array ( 
0 => Array ( 'ID' => 6, 'pageTitle' => 'First', 'pageContent' => 'http://localhost/cms/1', 'parentID' => 0 ),
1 => Array ( 'ID' => 7, 'pageTitle' => 'Second', 'pageContent' => 'http://localhost/cms/2', 'parentID' => 6 ),
2 => Array ( 'ID' => 8, 'pageTitle' => 'Third', 'pageContent' => 'http://localhost/cms/3', 'parentID' => 6 ) ,
3 => Array ( 'ID' => 9, 'pageTitle' => 'Four', 'pageContent' => 'http://localhost/cms/4', 'parentID' => 0 ) 
) ;

And my result should be like this

$final_ar = array(

  0  => array ( 'ID' => 6, 'pageTitle' => 'First', 'pageContent' => 'http://localhost/cms/1', 'parentID' => 0 , 

    'sub_items' => array( 
         0 => array('ID' => 7, 'pageTitle' =>'second', 'pageContent' => 'http://localhost/cms/2', 'parentID' => 6),
         1 => array('ID' => 8, 'pageTitle' => 'Third', 'pageContent' => 'http://localhost/cms/3', 'parentID' => 6),
     )
  ), 
  1 => array('ID' => 9, 'pageTitle' => 'Four', 'pageContent' => 'http://localhost/cms/4', 'parentID' => 0)
);

And here is my code

$final_ar = array();

foreach ($raw_ar as $value) {
if($value['parentID'] ==0){
    $final_ar[] = $value;
}
else{
    $pID = $value['parentID'];
    foreach ($final_ar as $value1) {
        //echo $value1['ID'].'-'.$pID;
        if($value1['ID'] == $pID){
            //if(isset($value1['sub_items'])){
                $value1['sub_items'][] = $value;
            //}else
                //$value1['sub_items'] = $value;
        }
        $temp_ar[] = $value1;
    }
    $exist = 0; 
    foreach ($final_ar as $key => $val) {
        # code...
        if($val['ID'] == $temp_ar['ID']){
            unset($final_ar[$key]);
            $final_ar[$key] = $temp_ar;
            $exist =1;
            break;
        }
    }
    if($exist == 0)
    $final_arr[] = $temp_ar;
    //$parent_key = array_column($raw_ar,'ID', 'parentID');     
}
}
print_r($final_arr);

And I tried to code it with sub_items . But it helps to create array. But I don't know how to remove existing array once it modifies. It gives the result like this.

Array ( [0] => Array ( [0] => Array ( [ID] => 6 [pageTitle] => First [pageContent] => http://localhost/cms/1 [parentID] => 0 [sub_items] => Array ( [0] => Array ( [ID] => 7 [pageTitle] => Second [pageContent] => http://localhost/cms/2 [parentID] => 6 ) ) ) ) [1] => Array ( [0] => Array ( [ID] => 6 [pageTitle] => First [pageContent] => http://localhost/cms/1 [parentID] => 0 [sub_items] => Array ( [0] => Array ( [ID] => 7 [pageTitle] => Second [pageContent] => http://localhost/cms/2 [parentID] => 6 ) ) ) [1] => Array ( [ID] => 6 [pageTitle] => First [pageContent] => http://localhost/cms/1 [parentID] => 0 [sub_items] => Array ( [0] => Array ( [ID] => 8 [pageTitle] => Third [pageContent] => http://localhost/cms/3 [parentID] => 6 ) ) ) ) ) 

Upvotes: 0

Views: 233

Answers (2)

Parantap Parashar
Parantap Parashar

Reputation: 2010

Try this:

function formatArray($nonFormattedArray) {

    $formattedArray = [];
    $subItems = [];

    foreach ($nonFormattedArray as $item) {
        $pid = $item['parentID'];

        if ($pid != 0) {
            if (isset($subItems[$pid]))
                $subItems[$pid][] = $item;
            else
                $subItems[$pid] = [$item];
        } else
            $formattedArray[] = $item;
    }

    foreach ($formattedArray as $key => $parent) {
        resolveChild($formattedArray[$key], $subItems);
    }

    return $formattedArray;
}

function resolveChild(&$parent, &$subItems) {
    //return if no child
    if (!isset($subItems[$parent['ID']]))
        return $parent;

    foreach ($subItems[$parent['ID']] as $key => $child) {
        if (isset($parent['sub_items']))
            $parent['sub_items'][] = resolveChild($subItems[$parent['ID']][$key], $subItems);
        else
            $parent['sub_items'] = [resolveChild($subItems[$parent['ID']][$key], $subItems)];
     }

    return $parent;
}

Now, formatArray($nonFormattedArray) should return your desired answer.

This will be independent of the order of your parent and child items and will reduce the total iteration count and execution time.

This will produce an Array as deep as the inheritance in the data.

Note that execution time will increase with the increment in inheritance level.

Upvotes: 1

u_mulder
u_mulder

Reputation: 54831

So many code you have here.

Here's my version:

foreach ($raw_ar as $value) {
    if ($value['parentID'] == 0) {
        $final_ar[$value['ID']] = $value;
    }
}

foreach ($raw_ar as $value) {
    $parent_id = $value['parentID'];
    if (0 < $parent_id) {
        if (!isset($final_ar[$parent_id]['sub_items'])) {
            $final_ar[$parent_id]['sub_items'] = [];
        }

        $final_ar[$parent_id]['sub_items'][] = $value;
    }
}

$final_ar = array_values($final_ar);    // if you need 0-indexed array

If you're 100% sure that parent items in your array come before child ones - you can join both foreaches into one:

foreach ($raw_ar as $value) {
    $parent_id = $value['parentID'];
    if ($parent_id == 0) {
        $final_ar[$value['ID']] = $value;
    } else {
        if (!isset($final_ar[$parent_id]['sub_items'])) {
            $final_ar[$parent_id]['sub_items'] = [];
        }

        $final_ar[$parent_id]['sub_items'][] = $value;
    }
}

$final_ar = array_values($final_ar);    // if you need 0-indexed array

Upvotes: 1

Related Questions