Mark Bucknell
Mark Bucknell

Reputation: 447

Remove elements from a flat array if found in a subarray of a multidimensional array

I have 2 arrays:

$network_keys = ['7 ADELAIDE', '7TWO ADELAIDE'];

$dblist = [
    [
        'PrpMedia' => [
            'id' => 3,
            'network_key' => '7 ADELAIDE',
            'media_id' => 43
        ],
        'Media' => [
            'id' => 43,
            'media_type_id' => 5,
            'media_location_id' => 4,
            'media_name' => 'Channel 7 ADELAIDE',
            'deleted' => false
        ]
    ],
    [
        'PrpMedia' => [
            'id' => 4,
            'network_key' => 'VIC 1HD BENDIGO',
            'media_id' => 42
        ],
        'Media' => [
            'id' => 42,
            'media_type_id' => 5,
            'media_location_id' => 4,
            'media_name' => '7MATE',
            'deleted' => false
        ]
    ]
];

I want to find which values from $network_keys do not exist in $dbList.

To be clear, we are looking in the ['PrpMedia']['network_key'] subarray of each $dblist row.

Expected array:

$difference = ['7TWO ADELAIDE'];

Upvotes: 0

Views: 50

Answers (2)

mickmackusa
mickmackusa

Reputation: 47894

It is not necessary to prepare the filtering array with array_map() before performing the filtration. Just use array_udiff().

In the callback, the $a and $b variables can come from either array.

Attempt to access the specified subarray column value; if it doesn't exist then assume the variable holds a value from the opposite array and use the string value. Demo

var_export(
    array_udiff(
        $network_keys,
        $dblist,
        fn($a, $b) => ($a['PrpMedia']['network_key'] ?? $a)
                      <=>
                      ($b['PrpMedia']['network_key'] ?? $b)
    )
);

Output:

array (
  1 => '7TWO ADELAIDE',
)

Upvotes: 0

trincot
trincot

Reputation: 350147

You could do it with a combination of array_map and array_diff:

$diff = array_diff($network_keys, array_map(function($v) {
    return $v['PrpMedia']['network_key'];
}, $dblist));

In the example you give, you will get the value of $network_keys, because none of them occur in the searched array.

The code first extracts all the ['PrpMedia']['network_key'] values from $network_keys into an array that will have the same flat structure as $dblist. Then it simply takes the difference, only keeping the elements of $dblist that do not occur in that intermediate array.

Be aware that this code assumes the searched key ['PrpMedia']['network_key'] exists in all of the elements of $network_keys. If this cannot be assumed to be always the case, then add a check, like this:

$diff = array_diff($network_keys, array_map(function($v) {
    return isset($v['PrpMedia']['network_key']) 
        ? $v['PrpMedia']['network_key']
        : null;
}, $dblist));

This will also work correctly if the ['PrpMedia'] key is not present for one of the elements.

Upvotes: 2

Related Questions