erol_smsr
erol_smsr

Reputation: 1496

Filter the rows of an array with four levels based on a column value in its deepest level

I have an array that looks like the following and I receive it from an API and therefore, can't change it:

[
    [
        'id' => '123',
        'title' => 'Test',
        'categories' => [
            [
                'id' => 1
            ]
        ]
    ],
    [
        'id' => '456',
        'title' => 'Test',
        'categories' => [
            [
                'id' => 2
            ]
        ]
    ]
]

I want to only get the complete array which contains 'categories' => [ 'id' => 1 ]

I've tried something like this:

$filteredArray = array_filter($array, function ($value) {
    return ($value['categories'] === 1);
});

This results in an empty array. How do I achieve this?

Upvotes: 1

Views: 233

Answers (3)

mickmackusa
mickmackusa

Reputation: 48000

Although the sample data only contains one entry with an id element per subset, I'll assume multiple subarray rows are possible.

Code: (Demo)

var_export(
    array_filter(
        $array,
        fn($row) => array_column($row['categories'], 'id', 'id')[1] ?? null
    )
);

As a slight microoptimization, using a conditionally breakable loop inside the callback can be used at the expense of more verbose code. (Demo)

var_export(
    array_filter(
        $array,
        function($row) {
            foreach ($row['categories'] as ['id' => $id]) {
                if ($id !== 1) {
                    return false;
                }
            }
            return true;
        }
    )
);

Upvotes: 0

Cornel Raiu
Cornel Raiu

Reputation: 3005

This would do it. You need to make sure you go all the way to the deepest level for filtering.

Not the cleanest solution ( there are probably nicer ones ), but it works:

Here is the sandbox for testing

$array = [
    [
        'id' => '123',
        'title' => 'Test',
        'categories' => [
            [
                'id' => 1
            ]
        ]
    ],
    [
        'id' => '456',
        'title' => 'Test',
        'categories' => [
            [
                'id' => 2
            ]
        ]
    ]
];

$filteredArray = array_filter($array, function ($value) {
    return array_filter($value['categories'], function($categories) { 
        return $categories['id'] === 1; 
    });
});

// Or the shorter version

$filteredArray = array_filter(
    $array, 
    fn($value) => array_filter(
        $value['categories'], 
        fn($categories) => $categories['id'] === 1
    )
);

print_r($filteredArray);

Upvotes: 2

erol_smsr
erol_smsr

Reputation: 1496

I have fixed the issue. The types were wrong. The category id in the array is of type int, and I was comparing it with a string value using ===. Casting either one of them to the type of the other has fixed the issue.

Upvotes: 0

Related Questions