0

I have an API that returns a HUGE array. I filter the returned data for the value "weekly" like this:

$results = array_filter($body['data'], function($item) {
        if(!isset($item['schedule']['type']))
            return false;
        return $item['schedule']['type'] == "weekly";
    });

The array $results looks like this:

Array
(
    [2] => Array
        (
            [title] => Title
            [description] => description
            [schedule] => Array (
                [type] => weekly
                [daily_time] => 16:00:00Z
                [weekdays] => Array
                    (
                        [0] => 1
                        [1] => 2
                        [2] => 3
                        [3] => 4
                        [4] => 5
                    )
            )
        [next_occurrence_time] => 2022-10-06T16:00:00+00:00
    )

    [3] => Array
        (
            [title] => Title 2
            [stream_title] => Title 2
            [stream_description] => description 2
            [schedule] => Array
            (
                [type] => weekly
                [start_time] => 
                [daily_time] => 16:00:00Z
                [scheduled_time] => 
                [weekdays] => Array
                    (
                        [0] => 2
                    )

            )
        [next_occurrence_time] => 2022-10-06T16:00:00+00:00
    )
    //More here...
)

The numbers represent a day of the week inside the [schedule][weekdays] array. I want to filter by specific day, so I can build a schedule. For example, I want to filter the $results array for and return every event on Tuesday.

My code only returns the data if Tuesday is the first [0] day in the array -> "Title 2". It does not return "Title" because Tuesday/2 is at the [1] position. How do I filter the associative array [schedule][weekday] and return any that contain "2"?

$filter = array("2");
$Tuesday = array_filter($results, function($e) use ($filter){
    return in_array($e['schedule']['weekdays'][0], $filter);
});
print_r($Tuesday);

changing to: return in_array($e['schedule']['weekdays'], $filter);

returns an empty array. I will need to do this for each day of the week and return the associated objects.

Dirty Bird Design
  • 5,333
  • 13
  • 64
  • 121
  • `$filter` contains a string, I suspect the values in `$weekdays` are numbers. Try `$filter = array(2);` – Barmar Oct 06 '22 at 20:18
  • $filter = array(2) returns empty object [] with ['schedule']['weekdays'][0], and with the [0] removed - which is my issue, not having to specify what position – Dirty Bird Design Oct 06 '22 at 20:24
  • Can you post `var_export($results);` so the data can be copied to a test site? – Barmar Oct 06 '22 at 20:25
  • 1
    If you don't want to specify the position, use `array_intersect`, in `in_array` – Barmar Oct 06 '22 at 20:26
  • Here is a condensed version of the returned array -> https://pastebin.com/4KUa0U1B – Dirty Bird Design Oct 06 '22 at 20:36
  • 1
    Please use either `var_dump` or `var_export`. `print_r` doesn't include quotes, so there's no way to tell the difference between a number and a numeric strings. – Barmar Oct 06 '22 at 20:38
  • And only `var_export()` can be used to copy and paste into a script. – Barmar Oct 06 '22 at 20:39
  • The actual returned array is over 25K lines - larger than pastebin allows. My mistake on sharing the condensed print_r version. http://dirtybirddesign.com/array.txt – Dirty Bird Design Oct 06 '22 at 20:49
  • 1
    I don't care if it's condensed, it just needs to be in a format I can use. – Barmar Oct 06 '22 at 20:52
  • Same task: [Implementing filter of nested arrays in PHP/Wordpress](https://stackoverflow.com/q/60290376/2943403) and here is [a "require all" technique](https://stackoverflow.com/a/59040842/2943403) – mickmackusa Oct 10 '22 at 03:31

1 Answers1

1

Use array_intersect() to tell if there's any overlap between the weekdays array and $filter.

array_filter($results, function($e) use ($filter){
    return array_intersect($e['schedule']['weekdays'], $filter);
});

array_intersect() converts everything to strings before comparing, so it's OK if the datatypes are different in the JSON than $filter.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Works as expected, thank you. If you were to do this for each day of the week (1 - 5) wold you make it a function and pass the day in as an arg? – Dirty Bird Design Oct 06 '22 at 20:55
  • Yes, that's what I'd do. But if you're only looking for 1 day, `$filter` doesn't need to be a list, so you can use `in_array($day, $e['schedule']['weekdays'])` – Barmar Oct 06 '22 at 21:00
  • I need to build for all 5 days of work week. What array function would help here? – Dirty Bird Design Oct 06 '22 at 21:07
  • No array needed. Use a `for` loop: `for ($day = 1; $day <= 5; $day++)` – Barmar Oct 06 '22 at 21:08
  • for ($day = 1; $day <= 5; $day++) { array_filter($results, function($e) use($filter){ return array_intersect($e['schedule']['weekdays'], $day); – Dirty Bird Design Oct 06 '22 at 21:14
  • NO. Go back and read my comment where I said you don't use `array_intersect`. And you need to change `use($filter)` to `use($day)` – Barmar Oct 06 '22 at 21:18
  • 1
    You don't seem to be thinking about what you're doing, just coding randomly. – Barmar Oct 06 '22 at 21:19
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/248608/discussion-between-dirty-bird-design-and-barmar). – Dirty Bird Design Oct 06 '22 at 21:28