简体   繁体   中英

Sort 2nd nested array by value in 3rd with php

Need to sort second nested array by a value n the third with php; 'Start Time'. Thinking maybe usort is the key. Posting the nested arrays of @week @day @class as well as a usort call and function I've been trying variations on.

Array
(
  [Sunday] => Array
    (
        [0] => Array
            (
                [Class Name] => Fun Class
                [Instructor] => Fun Teacher
                [Class Type] => Yoga Stretches
                [Start Time] => 1899-12-30T17:00:00
                [End Time] => 1899-12-30T18:15:00
                [Day Name] => Sunday
            )

        [1] => Array
            (
                [Class Name] => Another Fun Class
                [Instructor] => Same Fun Teacher
                [Class Type] => Relaxation
                [Start Time] => 1899-12-30T18:30:00
                [End Time] => 1899-12-30T19:45:00
                [Day Name] => Sunday
            )

        [2] => Array
            (
                [Class Name] => Hot Yoga without Cold
                [Instructor] => Dave the Flexible
                [Class Type] => Hot Hot Yoga
                [Start Time] => 1899-12-30T09:00:00
                [End Time] => 1899-12-30T10:30:00
                [Day Name] => Sunday
            )
    )
    [Monday] => Array
    (
        [0] => Array
            (
                [Class Name] => Mellow Chill Hang
                [Instructor] => Guru Awesome
                [Class Type] => Yoga Namaste
                [Start Time] => 1899-12-30T12:00:00
                [End Time] => 1899-12-30T13:00:00
                [Day Name] => Monday
            )
   )
)

Have tried (variations on):

foreach ($week_schedule as $day)//$week_schedule = the outer array
    {
     for($j=count($week_schedule);$j>=0;$j--)
         usort($day,'sortTimes');
}

function sortTimes( $a, $b ) {
    return strtotime($a["Start Time"]) - strtotime($b["Start Time"]);
 }

Have tried using a single foreach with extracting values ($day => $class). I bet this won't end up requiring much code.

Try with array_map to get into the nested elements and your Start Time has a 'T' character which I think cannot be used with strtotime so I've removed it:

function custom_map( $array ) {
    usort( $array, function( $a, $b ) {
        return ($a['Start Time']<$b['Start Time'])? -1 : 1;
    });
    return $array;
}

$new_array = array_map( "custom_map", $week_schedule );

var_dump($new_array);

Demo

Explanation:

Since you were interested in learning how this works, I did a few research myself and came up with this explanation:

First of all, you should know what array_map() and usort() are for.

array_map() from PHP Doc:

array_map() returns an array containing all the elements of array1 after applying the callback function to each one.

Syntax:

array array_map ( callable $callback , array $array1 [, array $... ] )

In simple words, array_map() will pass each element of your array to the callback function that you specify. And it returns an array (with the changed values, that you have done in that callback function).

Now usort(),

usort() from PHP Doc:

This function will sort an array by its values using a user-supplied comparison function. If the array you wish to sort needs to be sorted by some non-trivial criteria, you should use this function.

Syntax:

bool usort ( array &$array , callable $value_compare_func )

So, usort() basically compares each array element in order to sort it in the correct order. The line that you see here:

return ($a['Start Time']<$b['Start Time'])? -1 : 1;

basically translates as:

 if $a['Start Time'] is lesser than $b['Start Time'], then return -1 so
 that $a can come before $b

with values:

$a['Start Time'] = '1899-12-30T09:00:00'; //3rd element
$b['Start Time'] = '1899-12-30T17:00:00'; //1st element

Now clearly, $a which is the third element is lesser than the 1st element $b, thus $a will be positioned before it. usort() makes check against every combination from start to end in order to sort.

Now, coming back to array_map(), the reason we are using it is because you have nested arrays.

What the array_map() actually does is, passes all your @days to the usort. And then the usort takes all your @class and sorts accordingly. If you see the following demo, where your @weeks have been taken out only @days and @class present, the above code will not work and will throw you errors of 'Start Time' not being found because you are trying to traverse through 2 nested arrays when only 1 is present:

Demo

For the above structure, the right method will be to implement usort directly without using array_map like:

Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM