phparraysmultidimensional-arrayarray-intersect

array_intersect() with 2d arrays in php


I am trying to filter 2d arrays which satisfy two conditions. But, it not works as expected. I figured out that error is in array_intersect() function. Why array_intersect() not works correctly here.Is there another way to do this without iteration.

<?php
            error_reporting(0);
            $students = [
                ["name"=> 'k. l.james', "grade"=>8],
                ["name"=> 'k. l.james', "grade"=>9],
                ["name"=> 'e. musk', "grade"=>8],
                ["name"=> 'jone', "grade"=>9],
            ];
        
            function filterByGrade($grade){
                global $students ;
                if (empty($grade)){
                    return $students ;
                }else{
        
                return array_filter($students , function($record) use($grade){
                    return ($record['grade'] == $grade);
                });
            }
            }
        
            function filterByName($name){
                global $students;
                if (empty($name)){
                    return $students;
                }else{
                
                return array_filter($students, function($record) use($name){
                    return (strcasecmp(str_replace(' ','',$record['name']),str_replace(' ','',$name)) == 0);
                });
            }
            }
            print_r(filterByGrade(8));
            echo "<br/>";
            print_r(filterByName('k.l.james'));
            echo '<br/>';
            print_r(array_intersect(filterByGrade(8), filterByName('k.l.james')));
        ?>
    

results are;

    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ) [2] => Array ( [name] => e. musk [grade] => 8 ) )
    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ) [1] => Array ( [name] => k. l.james [grade] => 9 ) )
    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ) [2] => Array ( [name] => e. musk [grade] => 8 ) )

I expect the last line of result as,

    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ))

If I interchanged the two arrays in array_intersect() as follows, the results are different.

    print_r(array_intersect(filterByName('k.l.james'),filterByGrade(8)));

Then,I get result as follows.

    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ) [2] => Array ( [name] => e. musk [grade] => 8 ) )
    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ) [1] => Array ( [name] => k. l.james [grade] => 9 ) )
    Array ( [0] => Array ( [name] => k. l.james [grade] => 8 ) [1] => Array ( [name] => k. l.james [grade] => 9 ) )

I noticed that only the first filtered array in array_intersect() is printed despite of considering the intersection of the two arrays.


Solution

  • You can create a function to filter students using multiple conditions, instead of trying to combine the 2 results.

    The function :

    /**
     * Here, $condition array of keys/values used to filter $data.
     * ex: ['name' => 'jone', 'grade' => 9]
     */
    function filterArray($data, $conditions)
    {
        if (empty($conditions)) {
            return $data;
        }
        
        return array_filter($data, function($record) use ($conditions) {
            // Check all given conditions
            foreach ($conditions as $key => $value) {
                // If doesn't match, return false (don't keep in filtered array)
                if ($record[$key] != $value) return false;
            }
            // conditions passed, add to array
            return true;
        });
    }
    

    Usage :

    $students = [
        ["name"=> 'k. l.james', "grade" => 8],
        ["name"=> 'k. l.james', "grade" => 9],
        ["name"=> 'e. musk', "grade" => 8],
        ["name"=> 'jone', "grade" => 9],
    ];
    
    print_r(filterArray($students, ['grade' => 8]));
    // out : [["name"=> 'k. l.james', "grade" => 8],["name"=> 'e. musk', "grade" => 8]]
    
    print_r(filterArray($students, ['name' => 'k. l.james']));
    // out : [["name"=> 'k. l.james', "grade" => 8], ["name"=> 'k. l.james', "grade" => 9]]
    
    print_r(filterStudents($students, ['grade' => 8, 'name' => 'k. l.james']));
    // out : [["name"=> 'k. l.james', "grade" => 8]]
    

    Additional notes :