4

I have an associative multi dimensional array as below

$data = array();
$data = Array ( 
    [0] => Array ( [class] => 1styear [branch] => IT [Exam] => SEM1 [student name] => Alex [Bio] => Good Boy )
    [1] => Array ( [class] => 2ndyear [branch] => Finance [Exam] => SEM1 [student name] => Mark [Bio] => Intelligent )
    [2] => Array ( [class] => 2ndyear [branch] => IT [Exam] => SEM1 [student name] => Shaun [Bio] => Football Player ) 
    [3] => Array ( [class] => 1styear [branch] => Finance [Exam] => SEM2 [student name] => Mike [Bio] => Sport Player ) 
    [4] => Array ( [class] => 1styear [branch] => IT [Exam] => SEM2 [student name] => Martin [Bio] => Smart  )
    [5] => Array ( [class] => 1styear [branch] => IT [Exam] => SEM1 [student name] => Philip [Bio] => Programmer  )
    )

I need to create new array based on similar element from above array. means I have to create array group. for e.g class element has repetitive 1styear and 2ndyear value. so it shouls create array of unique element. then again class is parent array and inside class array there should be branch based array and inside brance Exam array and inside Exam array there should be associative array of student name and bio.

so basically array should look like this

array(
    "1styear" => array(
        "IT" => array(
            "SEM1" => array(
                array(
                    "student name" => "Alex",
                    "Bio" => "Good Boy"
                ),
                array(
                    "student name" => "Philip",
                    "Bio" => "Programmer"
                )
            ),
            "SEM2" => array(
                array(
                    "student name" => "Martin",
                    "Bio" => "Smart"
                )
            )
        )
    ),
    "2ndyear" => array(
        "Finance" => array(
            "SEM1" => array(
                array(
                    "student name" => "Mark",
                    "Bio" => "Intelligent"
                )
            ),
            "SEM2" => array(
                array(
                    "student name" => "Mike",
                    "Bio" => "Sport Player"
                )
            )
        )
    )
);

To make group based on class i did like below which is working fine but how to create array inside that

$classgroup = array();  
    foreach($data as $inarray){

         $classgroup[$inarray['class']][] = $inarray;
    }
    $classarray = array();
    foreach($classgroup as $key => $value){
            echo $key; // output is 1styear and secondyear 
            create array like above
    }

---------------------------------EDIT----------------------------------

from the below loop

foreach($data as $array){
        $grouped[$array["class"]][$array["branch"]][$array["Exam"]][]=array("student name"=>$array["student name"],"Bio"=>$array["Bio"]);
} 

i got expected o/p but if i need another o/p like this

expected o/p

array(
    '1styear' =>
        array (
            0 =>
                array(
                    'Exam' => 'SEM1',
                    'branch' =>
                        array (
                            0 => 'IT'
                        ),
                ),
            1 =>
                array(
                    'Exam' => 'SEM2',
                    'branch' =>
                        array (
                            0 => 'IT'
                        ),
                ),
        ),
    '2ndyear' =>
        array (
            0 =>
                array(
                    'Exam' => 'SEM1',
                    'branch' =>
                        array (
                            0 => 'Finance',
                        ),
                ),
            1 =>
                array(
                    'Exam' => 'SEM2',
                    'branch' =>
                        array (
                            0 => 'Finance'
                        ),
                )
        ),
)

i tried following loop but not getting o/p as expected

foreach($data as $array){
        $grouped[$array["class"]][]=array("Exam"=>$array["Exam"],"branch"=>$array["branch"]);
}
webpic
  • 443
  • 1
  • 10
  • 23

2 Answers2

2

A one-liner in a loop!

foreach($data as $array){
        $grouped[$array["class"]][$array["branch"]][$array["Exam"]][]=array("student name"=>$array["student name"],"Bio"=>$array["Bio"]);
}

$grouped produces:

Array(
    [1styear] => Array(
        [IT] => Array(
            [SEM1] => array(
                [0] => array(
                    [student name] => Alex,
                    [Bio] => Good Boy
                ),
                [1] => array(
                    [student name] => Philip,
                    [Bio] => Programmer
                )
            ),
            [SEM2] => array(
                [0] => array(
                    [student name] => Martin,
                    [Bio] => Smart
                )
            )
        ),
        [Finance] => array(
            [SEM2] => array(
                [0] => array(
                    [student name] => Mike,
                    [Bio] => Sport Player
                )
            )
        )
    ),
    [2ndyear] => array(
        [Finance] => array(
            [SEM1] => array(
                [0] => array(
                    [student name] => Mark,
                    [Bio] => Intelligent
                )
            )
        ),
        [IT] => array(
            [SEM1] => array(
                [0] => array(
                    [student name] => Shaun,
                    [Bio] => Football Player
                )
            )
        )
    )
)

Your follow up case, was MUCH more fun/challenging. I had to knock the dust off of some functions I don't play with very often. Check this out:

<?php
$data = array ( 
    array ( "class"=>"1styear","branch"=>"IT","Exam"=>"SEM1","student name"=>"Alex","Bio"=>"Good Boy"),
    array ( "class"=>"2ndyear","branch"=>"Finance","Exam"=>"SEM1","student name"=>"Mark","Bio"=>"Intelligent" ),
    array ( "class"=>"2ndyear", "branch"=>"IT","Exam"=>"SEM1","student name"=>"Shaun","Bio"=>"Football Player" ), 
    array ( "class"=>"1styear","branch"=>"Finance","Exam"=>"SEM2","student name"=>"Mike","Bio"=>"Sport Player" ), 
    array ( "class"=>"1styear","branch"=>"IT","Exam"=>"SEM2","student name"=>"Martin","Bio"=>"Smart"),
    array ( "class"=>"1styear","branch"=>"IT","Exam"=>"SEM1","student name"=>"Philip","Bio"=>"Programmer"  )
);
$class_keys=array_unique(array_column($data,"class"));  // create array of unique class values
$Exam_keys=array_unique(array_column($data,"Exam"));  // create array of unique Exam values
foreach($class_keys as $class_key){
    $i=0;  // "class" subarray index
    foreach($Exam_keys as $Exam_key){
        $q=array("class"=>$class_key,"Exam"=>$Exam_key);  // this array can have 1 or more pairs
        // create an array only of rows where $q's key-value pairs exist
        $qualifying_array=array_filter(
            $data,
            function($val)use($q){  
                if(count(array_intersect_assoc($val,$q))==count($q)){  // total pairs found = total pairs sought
                    return $val;
                }
            },
            ARRAY_FILTER_USE_BOTH
        );
        foreach($qualifying_array as $qa){  // push appropriate values into array
            $grouped2[$class_key][$i]["Exam"]=$qa["Exam"];
            $grouped2[$class_key][$i]["branch"][]=$qa["branch"];
        }
        if(isset($grouped2[$class_key][$i]["branch"])){  // ensure no duplicate values in "branch" subarray
            $grouped2[$class_key][$i]["branch"]=array_unique($grouped2[$class_key][$i]["branch"]);
        }
        ++$i;  // increment the index for each "class" subarray
    }
}
echo "<pre>";
print_r($grouped2);
echo "</pre>";

The output isn't identical to what you requested, but I think you were just showing what it should look like generally. If this isn't quite right, let me know.

array(
    [1styear]=>array(
        [0]=>array(
            [Exam]=>SEM1
            [branch]=>array(
                [0]=>IT
            )
        ),
        [1]=>array(
            [Exam]=>SEM2
            [branch]=>array(
                [0]=>Finance,
                [1]=>IT
            )
        )
    ),
    [2ndyear]=>array(
        [0]=>array(
            [Exam]=>SEM1
            [branch]=>array(
                [0]=>Finance,
                [1]=>IT
            )
        )
    )
)
halfer
  • 19,471
  • 17
  • 87
  • 173
mickmackusa
  • 37,596
  • 11
  • 75
  • 105
  • @webpic I'm not sure if `competitor` means `student name`, but just consider the nature of the one-liner's structure. If you want to preserve the associative keys, name them *in order* before `[]=` then place all indexed/nested arrays after the `=`. If you need more information, just ask (if it's too much of a departure from this question, you may need to ask a separate question. Either way, I'm happy to lend a hand. – mickmackusa Feb 27 '17 at 10:47
  • thats brilliance tnx . expected o/p. what if i only want array('finance','IT') IN branch array instead of array([0] => finance,[1]=>IT) . – webpic Feb 28 '17 at 06:38
  • @webpic you can remove the empty square brackets before the = sign, but then it will overwrite that loop's branch value (if there are multiple) for each occurrence. If you go with that technique, you can remove the following isset condition block, as there will never be duplicates to remove. – mickmackusa Feb 28 '17 at 07:01
  • if i remove [ ] from loop then it will only take single value , i just need to remove their index(key) and keep only values – webpic Feb 28 '17 at 07:24
  • @webpic In short, you can't have it both ways. If you are storing multiple values, you have two choices: create an array, or concatenate the values as a single string. You can concatenate the string value if you know exactly how the delimited string should look when you display it. Otherwise, and this is my recommendation, store the multiple values in the array. All array values require a key to exist -- they can be integers or strings, either way this shouldn't negatively impact your usage. – mickmackusa Feb 28 '17 at 09:45
  • @webpic I just changed `array_intersect()` to `array_intersect_assoc()` in the filter. It didn't cause any trouble in your case, because your values are unique in each row, but other cases (where multiple keys hold the same value) will yield false positive matches. Should be all good now. – mickmackusa Mar 01 '17 at 01:46
0

Maybe something like this (not tested)?

$newData = [];

foreach ($data as $row) {
   $student = [
      'student name' => $row['student name'],
      'Bio' => $row['Bio']
   ];
   $newData[$row['class']][$row['branch']][$row['exam']][] = $student;
}
Ray O'Donnell
  • 700
  • 4
  • 9