php - Filter multidimensional array using multiple rules from another multidimensional array

981

I have a multidimensional input array and another multidimensional array containing rules by which to filter the input array.

$array = [
    'tableData' => [
        [
            'booking_name' => 'abc/xyz/123',
            'pdg' => 'assure',
            'user_area' => 'es st',
            'release' => 'oss72',
            'start_date' => '2017-06-20 00:00:00',
            'end_date' => '2017-06-23 00:00:00',
            'asset_info' => [
                [
                    'status' => 10,
                    'manufacturer' => 'HP',
                    'model' => 'HP BL460C GEN8',
                    'hardware_color' => ''#0066b3'
                ]
            ],
            'full_name' => 'Valay Desai',
            'email_address' => '[email protected]'
        ],
        [
            'booking_name' => 'abc/xyz/123',
            'pdg' => 'assure',
            'user_area' => 'ls reca',
            'release' => 'oss72',
            'start_date' => '2017-06-20 00:00:00',
            'end_date' => '2017-06-23 00:00:00',
            'asset_info' => [
                [
                    'status' => 10,
                    'manufacturer' => 'SUN',
                    'model' => 'SUN GEN8',
                    'hardware_color' => '#0066b3'
                ]
            ],
            'full_name' => 'Chako Desai',
            'email_address' => '[email protected]'
        ]
    ]
];

$filterBy = [
    'booking_name' => 'abc',
    'pdg' => [
        ['name' => 'Invalid', 'value' => 'Invalid'],
        ['name' => 'assure', 'value' => 'assure']
    ],
    'user_area' => [
        ['name' => 'es st', 'value' => 'es st'],
        ['name' => 'Invalid', 'value' => 'Invalid'],
        ['name' => 'a&o', 'value' => 'a&o']
    ]
];

I understand thatarray_filter can be used to compare the values, but I'm not sure how to perform the multi-rule filtration on the data withintableData.

Ideal output should be the first element fromtableData because it hasbooking_name=abc,pdg=assure anduser_area=es st.

I tried with:

// bigarray is an originial array to be filtered
// filterObj is an array with multiple filter conditions
array_filter($bigarray, function ($val_array) use ($filterObj) {
    $intersection = array_intersect_assoc($val_array, $filterObj);
    return (count($intersection)) === count($filterObj);
});

This always returns blank array.

Update 1:

I've used below way to get objects who hasvisible:true. Tried similar for the asked question but couldn't able to get the ideal result.

$columnVisible = array(
    'visible' => 1,
);

$visibleColumns = array_filter($passedColumns, function ($val_array) use ($columnVisible) {
    $intersection = array_intersect_assoc($val_array, $columnVisible);
    return (count($intersection)) === count($columnVisible);
});

How do I apply multiple filtering conditions passed as an array of arrays on an associative array of arrays?

75

Answer

Solution:

Try this solution.

$filters = array('pdg'=>array('xyzabc'), 'user_area'=>array('ls reca'));
$filter_items = array();
foreach( $items['tableData'] as $item ){
    $i=0;
    $is_match = true;


 foreach( $filters as $key=>$value){
    //$is_match = true;
    if( !in_array( $item[$key], $value) ){
        $is_match = false;
        break;
    }
    //$is_match = true;
 }

 if( $is_match ){
    $filter_items[] = $item;
 }
}
377

Answer

Solution:

I don't think I would bother trying to wranglearray_intersect()-family functions for this task. These functions perform sorting while they iterate and this is not going to be ideal while returing pass/fail type evaluations.

I would simplify the filtering array's structure to make the processing more direct. Once thepdg anduser_area rules are flattened to their most meaningful parts, just callarray_filter() and write the three evaluations in a single return. This will enjoy the performance benefit of "short circuiting" so as soon as afalse outcome is encountered, thefalse will be returned without making needless extra evaluations.

I am nesting the output inside of atableData although I don't know if that's the exact output you desire. It is simple enough to unwrap the filtered array from the element.

Code: (Demo)

$filterBy['pdg'] = array_column($filterBy['pdg'], 'value');
$filterBy['user_area'] = array_column($filterBy['user_area'], 'value');

var_export(
    [
        'tableData' => 
        array_filter(
            $array['tableData'],
            function($row) use($filterBy) {
                return str_contains($row['booking_name'], $filterBy['booking_name'])
                    && in_array($row['pdg'], $filterBy['pdg'])
                    && in_array($row['user_area'], $filterBy['user_area']);
            }
        )
    ]
);

People are also looking for solutions to the problem: php - How to find out my own composer package stability?

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.