Search code examples
phparraysmultidimensional-arrayfilteringwhitelist

Filter rows of a 3d array where keys in a specific column satisfy a flat whitelist array


I need to filter a 3 dimensional array by the keys in one of its columns. I wish to retain any row which has contains all required keys from a declared whitelist array.

Sample Data:

[
    [
        'name' => 'Фізика',
        'disciplines' => [
            1 => 'Українська мова та література',
            4 => 'Математика',
            5 => 'Фізика',
            6 => 'Біологія',
        ],
        'priority' => [
            1 => 0,
            4 => 1,
            5 => 2,
            6 => 2,
        ]
    ],
    [
        'name' => 'Інформатика',
        'disciplines' => [
            1 => 'Українська мова та література',
            2 => 'Історія України',
            4 => 'Математика',
            12 => 'Іноземна мова',
        ],
        'priority' => [
            1 => 0,
            2 => 2,
            4 => 1,
            12 => 2,
        ]
    ],
    [
        'name' => 'Початкова освіта',
        'disciplines' => [
            1 => 'Українська мова та література',
            2 => 'Історія України',
        ],
        'priority' => [
            1 => 0,
            2 => 2,
        ]
    ],
]

I want to keep rows where their discipline array contains keys for all values in my flat array:

[2, 4, 12]

in_array() is not working for me. How can I filter this array structure using this array of required keys? From my sample data, only the second row should be kept.

var_dump() of larger array


Solution

    • Prepare your whitelist so that the required values are the keys of a flat array.
    • Call array_filter() to iterate each row of the sample array.
    • Try to eliminate as many elements from the whitelist array using the row's discipline keys. If there are none remaining, then the row satisfies the whitelist and should be retained.

    Code: (Demo)

    $get['disciplines'] = ['second' => 2, 'third' => 4, 'fourth' => 12];
    $filterBy = array_flip($get['disciplines']);
    
    var_export(
        array_filter(
            $array,
            fn($row) => !array_diff_key($filterBy, $row['disciplines'])
        )
    );