Search code examples
phparraysmultidimensional-arrayarrayofarrays

PHP How To Turn Nested Foreach Into An Array of Arrays (Multidimensional Array)


I'm sorry because I'm probably not going to use the correct vocabulary here, but I'm trying to figure out "how-to" modify the following code so that it creates the array of arrays (Multidimensional Array). This code creates the structure illustrated in the image below, but I want it to create the array of arrays (Multidimensional Array) instead.

Basically, I want the 1001, 1002, 1004, etc... to be the main array. The nested arrays will be the strings that has the #1001, #1002, etc... in them. You'll notice the # in the string corresponds with number in the original array.

$combinedAssignmentData = []; 
foreach($assignmentsYES as $key=>$assignedIDs){
  $levels = array($assignedIDs);
    foreach($levels as $key=>$level){
      echo "<strong>$level</strong><br>";
      foreach($studentIDsubmissions as $k=>$individualSubmission){
        if (strpos($individualSubmission, $level) !== false) {
          echo "--$individualSubmission<br>";
        }
      }
    }
}

var_export($assignmentsYES);

array ( 0 => '1001', 1 => '1002', 2 => '1004', 3 => '1005', 4 => '1007', 5 => '1008', 6 => '1009', 7 => '1015', 8 => '1028', 9 => '1029', )

var_export($studentIDsubmissions);

array ( 0 => '[email protected]|TD-Share Test #1001|NO', 1 => '[email protected]|TD-Share Test #1001|NO', 2 => '[email protected]|TD-Share Test #1001|NO', 3 => '[email protected]|TD-Share Test #1001|NO', 4 => '[email protected]|TD-No Excuse Reflection #1002|YES', 5 => '[email protected]|TD-No Excuse Reflection #1002|YES', 6 => '[email protected]|TD-No Excuse Reflection #1002|YES', 7 => '[email protected]|TD-About Me #1004|YES', 8 => '[email protected]|TD-Calendar #1007|YES', 9 => '[email protected]|TD-Wage Tracker #1008|YES', 10 => '[email protected]|TD-Stock Portfolio #1009|YES', 11 => '[email protected]|TD-Collaboration #1005|YES', 12 => '[email protected]|TD-Stock Portfolio #1009|YES', 13 => '[email protected]|TD-Collaboration #1005|YES', 14 => '[email protected]|TD-Dream Vacation Presentation #1015|YES', )

enter image description here

Any help is greatly appreciated! Todd


Solution

  • Here you go

    $assignmentsYES = array ( 0 => '1001', 1 => '1002', 2 => '1004', 3 => '1005', 4 => '1007', 5 => '1008', 6 => '1009', 7 => '1015', 8 => '1028', 9 => '1029', );
    $studentIDsubmissions = array ( 0 => '[email protected]|TD-Share Test #1001|NO', 1 => '[email protected]|TD-Share Test #1001|NO', 2 => '[email protected]|TD-Share Test #1001|NO', 3 => '[email protected]|TD-Share Test #1001|NO', 4 => '[email protected]|TD-No Excuse Reflection #1002|YES', 5 => '[email protected]|TD-No Excuse Reflection #1002|YES', 6 => '[email protected]|TD-No Excuse Reflection #1002|YES', 7 => '[email protected]|TD-About Me #1004|YES', 8 => '[email protected]|TD-Calendar #1007|YES', 9 => '[email protected]|TD-Wage Tracker #1008|YES', 10 => '[email protected]|TD-Stock Portfolio #1009|YES', 11 => '[email protected]|TD-Collaboration #1005|YES', 12 => '[email protected]|TD-Stock Portfolio #1009|YES', 13 => '[email protected]|TD-Collaboration #1005|YES', 14 => '[email protected]|TD-Dream Vacation Presentation #1015|YES', );
    
    $combinedAssignmentData = []; 
    foreach($assignmentsYES as $key=>>$level){
            $combinedAssignmentData[$level] = 
                    array_filter(
                        $studentIDsubmissions,
                        function($item)use($level){
                            return strpos($item, '#'.$level) !== false;
                        }
                    );
    }
    
    print_r($combinedAssignmentData);
    

    Output

    Array
    (
        [1001] => Array
            (
                [0] => [email protected]|TD-Share Test #1001|NO
                [1] => [email protected]|TD-Share Test #1001|NO
                [2] => [email protected]|TD-Share Test #1001|NO
                [3] => [email protected]|TD-Share Test #1001|NO
            )
    
        [1002] => Array
            (
                [4] => [email protected]|TD-No Excuse Reflection #1002|YES
                [5] => [email protected]|TD-No Excuse Reflection #1002|YES
                [6] => [email protected]|TD-No Excuse Reflection #1002|YES
            )
    
        [1004] => Array
            (
                [7] => [email protected]|TD-About Me #1004|YES
            )
    
        [1005] => Array
            (
                [11] => [email protected]|TD-Collaboration #1005|YES
                [13] => [email protected]|TD-Collaboration #1005|YES
            )
    
        [1007] => Array
            (
                [8] => [email protected]|TD-Calendar #1007|YES
            )
    
        [1008] => Array
            (
                [9] => [email protected]|TD-Wage Tracker #1008|YES
            )
    
        [1009] => Array
            (
                [10] => [email protected]|TD-Stock Portfolio #1009|YES
                [12] => [email protected]|TD-Stock Portfolio #1009|YES
            )
    
        [1015] => Array
            (
                [14] => [email protected]|TD-Dream Vacation Presentation #1015|YES
            )
    
        [1028] => Array
            (
            )
    
        [1029] => Array
            (
            )
    
    )
    

    Sandbox

    *PS I added a # in here strpos($item, '#'.$level), which will improve the accuracy a bit. It would be better to use a regular expression (in the array filter callback)

    function($item)use($level){
       return preg_match('/#'.$level.'\|/', $item); //match `#{id}|`
    }
    

    Consider for example matching 1001 to id 10012 ~ strpos will just match the 1001 part with no regard.

    If the oddly numbered keys for the sub array bug you you can wrap the array_filter in array_values(array_filter(....)); to reset them. Array filter retains the keys from the original array. In most cases the keys don't really matter, so I wouldn't worry about it unless you really have to.

    Update

    After thinking about it and posting this

    be better to use a regular expression

    Why don't we go with this one:

    $assignmentsYES = array ( 0 => '1001', 1 => '1002', 2 => '1004', 3 => '1005', 4 => '1007', 5 => '1008', 6 => '1009', 7 => '1015', 8 => '1028', 9 => '1029', );
    $studentIDsubmissions = array ( 0 => '[email protected]|TD-Share Test #1001|NO', 1 => '[email protected]|TD-Share Test #1001|NO', 2 => '[email protected]|TD-Share Test #1001|NO', 3 => '[email protected]|TD-Share Test #1001|NO', 4 => '[email protected]|TD-No Excuse Reflection #1002|YES', 5 => '[email protected]|TD-No Excuse Reflection #1002|YES', 6 => '[email protected]|TD-No Excuse Reflection #1002|YES', 7 => '[email protected]|TD-About Me #1004|YES', 8 => '[email protected]|TD-Calendar #1007|YES', 9 => '[email protected]|TD-Wage Tracker #1008|YES', 10 => '[email protected]|TD-Stock Portfolio #1009|YES', 11 => '[email protected]|TD-Collaboration #1005|YES', 12 => '[email protected]|TD-Stock Portfolio #1009|YES', 13 => '[email protected]|TD-Collaboration #1005|YES', 14 => '[email protected]|TD-Dream Vacation Presentation #1015|YES', );
    
    $combinedAssignmentData = []; 
    foreach($assignmentsYES as $key=>$level){
        $combinedAssignmentData[$level] = preg_grep('/#'.$level.'\|/', $studentIDsubmissions);
    }
    
    print_r($combinedAssignmentData);
    

    Using Preg Grep is a bit cleaner then array filter and a callback with a regular expression. I also realized you had a superficial loop in there $levels = array($assignedIDs); or basically $levels = array($level); or just $level.

    Same output as before

    Sandbox