1

Regarding this multidimensional array:

[ 7 => [ ['12:45', 'E1', 'B EXTREME 30'], ['10:15', 'E1', 'B SHAPE 30'], ], 1 => [ ['09:30', 'E2', 'CYCLING VIRTUAL 50'], ['10:30', 'E1', 'BODY PUMP VIRTUAL 60'], ['11:45', 'E1', 'BODY BALANCE VIRTUAL 60'], ], 2 => [ ['14:45', 'E2', 'CYCLING VIRTUAL 50'], ['17:00', 'E1', 'POSTURA ALONGAMENTO 60'], ['09:15', 'E1', 'BODY PUMP 50'], ], ]; 

The first key, of each first level array, are days of the week (day 7, day 1 and day 2).

The arrays inside each first level array contain hour (09:45), rooms (E1) and description (B EXTREME 30).

I tried to sort this multidimensional array by the second levels array hour value. I used usort(), ksort(), array_multisort(), and some custom made functions for sorting the array as I need without luck.

The inside arrays must be sorted by ascending order, like this (example with day 2):

09:15 -> 14:45 -> 17:00 

How can I achieve this?

3
  • So you don't want to sort by key as the title states, but sort by the time in each sub-array? Commented Apr 1, 2019 at 19:49
  • Yes... i need to sort by the time. My apologies... i will edit the question. Commented Apr 1, 2019 at 19:56
  • Please post expected output Commented Apr 2, 2019 at 7:18

3 Answers 3

1

Assuming your data is called $data. Iterate the outer array, and apply a sort on each mid-level array, based on the time-part (in the innermost arrays). As your times are always formatted as "hh:ss", a string comparison in the usort callback does the job:

foreach ($data as &$events) { usort($events, function($a, $b) { return strcmp($a[0], $b[0]); }); } 

Note the & in the foreach: this makes sure you sort the original data, and not a copy of it.

If you want to create a new array, let's say $result, then do this (no & here!):

foreach ($data as $day => $events) { usort($events, function($a, $b) { return strcmp($a[0], $b[0]); }); $result[$day] = $events; } 
Sign up to request clarification or add additional context in comments.

4 Comments

No luck, the result is an empty array. $ar = []; foreach ($mapadeaulas_mobile as &$events) { usort($events, function($a, $b) { $ar = strcmp($a[0], $b[0]); }); }
Works here: 3v4l.org/TgMc6 What is $ar? This solution sorts the result in the original array. If you want the result in $ar , then first assign the array to $ar and do the foreach on $ar. Doing $ar = strcmp(...) makes no sense. You must return strcmp(...)
See addition to my answer.
Thank you. usort() plus strcmp() ordered the arrays by time in correct maner.
0

usort — Sort an array by values using a user-defined comparison function. Lets create a function where we compare time of two events.

This is part of your array

$array = [ 2 => [ 0 => [ 0 => '14:45', 1 => 'E2', 2 => 'CYCLING VIRTUAL 50' ], 1 => [ 0 => '17:00', 1 => 'E1', 2 => 'BODY PUMP VIRTUAL 60' ], 2 => [ 0 => '09:15', 1 => 'E1', 2 => 'BODY BALANCE VIRTUAL 60' ], ], ]; 

This is an example how to sort items for one day (day 2)

usort($array[2], function ($a, $b) { $time_a = strtotime($a[0]); // convert string to a unix timestamp to compare int $time_b = strtotime($b[0]); return $time_a - $time_b; }); 

Output using print_r($array);

Array ( [2] => Array ( [0] => Array ( [0] => 09:15 [1] => E1 [2] => BODY BALANCE VIRTUAL 60 ) [1] => Array ( [0] => 14:45 [1] => E2 [2] => CYCLING VIRTUAL 50 ) [2] => Array ( [0] => 17:00 [1] => E1 [2] => BODY PUMP VIRTUAL 60 ) ) ) 

To sort all days we do in a loop, passing each day array as a reference using &:

foreach ($array as &$day) { usort($day, function ($a, $b) { $time_a = strtotime($a[0]); $time_b = strtotime($b[0]); return $time_a - $time_b; }); } 

Comments

0

The most succinct solution is to call sort() on each data set inside of a loop. This will compare data set counts (always 3 for your data), then the each column from left to right as needed (hour, then, rooms, then description). Because your hour values are unique within each data set, sorting on the remaining two columns will never be necessary. Demo

array_walk($array, fn(&$rows) => sort($rows)); var_export($array); 

If you wish to be more explicit about what is being compared while sorting then...

Call usort() and compare the first column only. Demo

array_walk( $array, fn(&$rows) => usort( $rows, fn($a, $b) => $a[0] <=> $b[0] ) ); var_export($array); 

Or isolate a column of values with array_column() and call array_multisort(). Demo

array_walk( $array, fn(&$rows) => array_multisort( array_column($rows, 0), $rows ) ); var_export($array); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.