0

I'm trying to filter a multidimensional array and return the number of entries found for a given category.

EDIT

I'm trying to avoid any use of foreach. Right now looking into using array_intersect but getting array to string conversion error. I'm doing this :

//filter array with category name
$category_array = array('T-Shirt','Men');
$filter_category = (array_intersect($products['result'], $category_array));
var_export($filter_category);//return data of filtered entries
echo $row_count=count($filter_category);//return number of entries

The desired result should return the exact same array seen below but only with filtered entries. If there is a better way to do what I'm trying to do. I'm opened!

This is what the data looks like unfiltered

$products={
        "code": 200,
        "result": [
            {
                "id": 121935189,
                "external_id": "5d27b7962ac2c1",
                "name": "RPROD7742019 Dark Green Bush Camo Men's T-Shirt ",
                "variants": 6,
                "synced": 6
            },
            {
                "id": 121934788,
                "external_id": "5d27b641b1f568",
                "name": "RPROD2282019 FOREST GREEN CAMO Men's T-shirt",
                "variants": 6,
                "synced": 6
            },
            {
                "id": 121934520,
                "external_id": "5d27b555048158",
                "name": "RPROD7542019 Men's Rash Guard T-Shirt Sweatshirt Long Sleeve",
                "variants": 7,
                "synced": 7
            },
            {
                "id": 121934241,
                "external_id": "5d27b467b817b4",
                "name": "RPROD4952019 Men's T-shirt",
                "variants": 6,
                "synced": 6
            },
            {
                "id": 121933767,
                "external_id": "5d27b34c3133a2",
                "name": "RPROD5872019 Men's T-shirt ",
                "variants": 6,
                "synced": 6
            },
            {
                "id": 121933319,
                "external_id": "5d27b12e253032",
                "name": "RPROD7662019 DARK GREEN CAMO Men's T-Shirt - Men",
                "variants": 6,
                "synced": 6
            },
            {
                "id": 121931543,
                "external_id": "5d27afd7c949b8",
                "name": "RPROD1192019 Jungle Camo Men's T-Shirt - Men",
                "variants": 6,
                "synced": 6
            },
            {
                "id": 121930567,
                "external_id": "5d27ae02dd00a8",
                "name": "RPROD7572019 Camo Short sleeve men’s t-shirt - Men",
                "variants": 6,
                "synced": 6
            },
            {
                "id": 121930354,
                "external_id": "5d27ad2a338399",
                "name": "RPROD8412019 Camo Men's T-shirt - Men",
                "variants": 6,
                "synced": 6
            },
            {
                "id": 121665999,
                "external_id": "5d251acde94bc7",
                "name": "RPROD3042019 Champion Dad Cap Trucker Cap Men",
                "variants": 2,
                "synced": 2
            },
            {
                "id": 121665890,
                "external_id": "5d251a50cb6a82",
                "name": "RPROD7162019 Vintage Cotton Twill Cap Trucker Cap Men Women",
                "variants": 3,
                "synced": 3
            },
            {
                "id": 121665703,
                "external_id": "5d2519cba9fea7",
                "name": "RPROD4872019 Dad hat Trucker Cap Men Women",
                "variants": 1,
                "synced": 1
            },
            {
                "id": 121665596,
                "external_id": "5d251972bd8b36",
                "name": "RPROD2492019 Dad hat Trucker Cap Men Women",
                "variants": 1,
                "synced": 1
            },
            {
                "id": 121665533,
                "external_id": "5d25193756ac83",
                "name": "RPROD5362019 Trucker Cap Dad hat Men Women",
                "variants": 5,
                "synced": 5
            },
            {
                "id": 121665382,
                "external_id": "5d2518ae661cf3",
                "name": "RPROD3082019 Cotton Cap Trucker Cap Dad Hat Men Women",
                "variants": 7,
                "synced": 7
            },
            {
                "id": 121665266,
                "external_id": "5d2518395f7b28",
                "name": "RPROD6372019 Trucker Cap Men Women",
                "variants": 1,
                "synced": 1
            },
            {
                "id": 121665141,
                "external_id": "5d2517dc928059",
                "name": "RPROD8112019 Trucker Cap Men Women",
                "variants": 9,
                "synced": 9
            },
            {
                "id": 121664869,
                "external_id": "5d25171b371fa4",
                "name": "RPROD7232019 Trucker Cap Men Women",
                "variants": 4,
                "synced": 4
            },
            {
                "id": 121664726,
                "external_id": "5d2516c175ad54",
                "name": "RPROD4112019 Trucker Cap Men Women",
                "variants": 5,
                "synced": 5
            },
            {
                "id": 121664599,
                "external_id": "5d251659e8a218",
                "name": "RPROD7002019 Trucker Cap Men Women",
                "variants": 1,
                "synced": 1
            },
            {
                "id": 121664477,
                "external_id": "5d251609908887",
                "name": "RPROD3232019 Trucker Cap Men Women",
                "variants": 5,
                "synced": 5
            },
            {
                "id": 121664346,
                "external_id": "5d2515ade45543",
                "name": "RPROD6702019 Trucker Cap - Men Women",
                "variants": 5,
                "synced": 5
            },
            {
                "id": 121664113,
                "external_id": "5d2515167e62e4",
                "name": "RPROD9422019 Cotton Cap Dad Hat Women Men",
                "variants": 8,
                "synced": 8
            },
            {
                "id": 121663700,
                "external_id": "5d2513fb5e6572",
                "name": "RPROD2552019 Cotton Trucker Cap Dad Hat Men Women",
                "variants": 4,
                "synced": 4
            },
            {
                "id": 121663350,
                "external_id": "5d251304231b28",
                "name": "RPROD2762019 Trucker Cap Men Women",
                "variants": 9,
                "synced": 9
            }
        ],
        "extra": [],
        "paging": {
            "total": 75,
            "offset": 0,
            "limit": 25
        }
    }
  • `preg_grep` doesn't work on multidimensional arrays. You're also giving the wrong arguments. You can only give it one regular expression. – Barmar Jul 14 '19 at 03:38
  • Can you show what the `$products['result']` array looks like? – Barmar Jul 14 '19 at 03:40
  • And what do you expect `$fl_array` to be? – Barmar Jul 14 '19 at 03:40
  • `array_intersect` also only works with 1-dimensional arrays. This is true of all the built-in array searching functions. – Barmar Jul 14 '19 at 04:25
  • `array_intersect()` doesn't know that it should look in the `Name` column. It also doesn't do substring matching, it looks for exact matches. – Barmar Jul 14 '19 at 04:26
  • whats the match criteria, all of those have "men" in the name, so they would all be filtered - no? `return the number of entries found for a given category` whats a category... – ArtisticPhoenix Jul 14 '19 at 04:30

2 Answers2

0

You can use array_filter for this. Turn your category array into a regular expression that matches all the words; see Regular Expression to MATCH ALL words in a query, in any order. Then use preg_match() in the filter function.

$regexp = '/(?=.*\bt-shirt\b)(?=.*\bmen\b)/i';
$fl_list = array_filter(function($p) use ($regexp) {
    return preg_match($regexp, $p['name']);
}, $products['result']);

I also used \b in my regular expressio, to make it match whole words. Otherwise, men will match women.

Things would be much easier if you had real keywords in your data, rather than trying to match words in a product name.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • I have edited my question. I want to avoid using a loop if possible. I'm now trying to use array_intersect to return a filtered array with category_name and gender and I still get same error. –  Jul 14 '19 at 04:15
  • I've update the answer to show how to do it with `array_fitler`. – Barmar Jul 14 '19 at 04:33
  • I would maybe suggest taking `$category_array` as an argument and then build the regex dynamically. But that should be trivial for them to add. – ArtisticPhoenix Jul 14 '19 at 05:16
0

Something like this:

$category_array = array('T-Shirt', 'camo');

print_r(
  array_intersect_key(
      $products['result'],
      preg_grep(
          '/(?=.*\b'.implode('\b)(?=.*\b', $category_array).'\b)/i',
          array_column($products['result'], 'name')
      )
  )
);

Output:

Array
(
    [0] => Array
        (
            [id] => 121935189
            [external_id] => 5d27b7962ac2c1
            [name] => RPROD7742019 Dark Green Bush Camo Men's T-Shirt 
            [variants] => 6
            [synced] => 6
        )

    [1] => Array
        (
            [id] => 121934788
            [external_id] => 5d27b641b1f568
            [name] => RPROD2282019 FOREST GREEN CAMO Men's T-shirt
            [variants] => 6
            [synced] => 6
        )

    [5] => Array
        (
            [id] => 121933319
            [external_id] => 5d27b12e253032
            [name] => RPROD7662019 DARK GREEN CAMO Men's T-Shirt - Men
            [variants] => 6
            [synced] => 6
        )

    [6] => Array
        (
            [id] => 121931543
            [external_id] => 5d27afd7c949b8
            [name] => RPROD1192019 Jungle Camo Men's T-Shirt - Men
            [variants] => 6
            [synced] => 6
        )

    [7] => Array
        (
            [id] => 121930567
            [external_id] => 5d27ae02dd00a8
            [name] => RPROD7572019 Camo Short sleeve men’s t-shirt - Men
            [variants] => 6
            [synced] => 6
        )

    [8] => Array
        (
            [id] => 121930354
            [external_id] => 5d27ad2a338399
            [name] => RPROD8412019 Camo Men's T-shirt - Men
            [variants] => 6
            [synced] => 6
        )

)

Sandbox

They all contain "Men" so I am not sure what the filter rules should be. Anyway, I used "camo" instead, after some tweaks.

PS, if you want to update the array then just do this instead of print_r:

$products['result'] = array_intersect_key( ... other code ... );

I can explain how it works if you want me too.

ArtisticPhoenix
  • 21,464
  • 2
  • 24
  • 38
  • `array_diff_key` removes all the matching items, I think he wants to find the matching items. – Barmar Jul 14 '19 at 04:34
  • So it should be `array_intersect_key`. – Barmar Jul 14 '19 at 04:35
  • You're imploding the array with `|`. I think he wants to match all of the categories, not any of them. See my answer for how to write that kind of regexp. – Barmar Jul 14 '19 at 04:49
  • Well considering there is no example of what it should match, all I have to go on is guess work... – ArtisticPhoenix Jul 14 '19 at 04:59
  • @Barmar - Updated (PS, I know what lookaheads are), but it was still a good suggestion. I just wish the question was more explicit. Lookarounds are about the only thing I haven't mastered in Regex ( I still struggle with them a bit ) ... lol. So thanks again. – ArtisticPhoenix Jul 14 '19 at 05:10
  • Before he edited it, there were two variables that he was trying to match, `$category` and `$subcategory`. In that context, it was clear that it needed to match both. – Barmar Jul 14 '19 at 18:50
  • Lookarounds are tricky for me, too. That happens to be an idiom I could copy from other questions. – Barmar Jul 14 '19 at 18:51
  • At least its not just me, ha ha. I find that 90% of the time I don't need them but the 10% that I do it's the only way to do it... That's probably part of it, I can get away without them in most cases. I know they work here, matching multiple things because they don't consume any characters... That and the `.*` wildcard bit. For example I get that it matches everything up to the "thing" then because it doesn't consume it basically starts from the beginning for the second one. – ArtisticPhoenix Jul 14 '19 at 22:56