views:

615

answers:

2

I have a very specific problem here. I have a multi-dimensional array that I want to sort first by half-hour time intervals, second by dates. The function array_multisort will not meet my requirements.

Example: I want:

array(array("time"=>"12:15",
            "date"=>"2009-03-24"),
      array("time"=>"12:10",
            "date"=>"2009-03-23"),
      array("time"=>"12:00",
            "date"=>"2009-03-24"),
      array("time"=>"11:30",
            "date"=>"2009-03-24"));

To end up as:

array(array("time"=>"11:30",
            "date"=>"2009-03-24"),
      array("time"=>"12:10",
            "date"=>"2009-03-23"),
      array("time"=>"12:00",
            "date"=>"2009-03-24"),
      array("time"=>"12:15",
            "date"=>"2009-03-24"));

I've tried to accomplish this with uksort in combination with my own sorting callback function. This is the code I am currently using:

uksort($myArray, "sortThirties");

function sortThirties($a, $b)
{
    //Get the two times as timestamps relative to today
    $one = strtotime($a['time']);
    $two = strtotime($b['time']);

    //Round them down to the nearest half-hour time
    $one = $one - ($one % 1800);
    $two = $two - ($two % 1800);

    //Return the difference if times are unequal
    //If times are equal, return the difference between dates.
    return ($one == $two ? strcmp($a['date'],$b['date']) : $one - $two);
}

Immediately after running this function, I print out the array with print_r(), and the order of the data appears to be random. What am I missing?

EDIT: It turns out, the order is completely random. I added this line to the sortThirties function:

echo "<BR>",$a['time']," ",$b['time'];

and all I got was 50 pages of <BR>'s.

I know the array is correctly structured because this code executed on the very same array gives me the unsorted data:

foreach($myArray AS $a)
{
    echo "<BR>",$a['date']," ",$a['time'];
}

The only thing I can think of is there must be a problem with uksort. Any thoughts?

+2  A: 

Very odd. I just tried your code on an array similar to the one you provided, and it worked great. Possibilities:

  • extra whitespace on any of the array times/dates?
  • PHP version differences? I noticed that the return value of strtotime() was changed in PHP version 5.1.0
zombat
Some versions of PHP require the date to be passed with the time in strtotime. This could be his problem.
gradbot
I have tested this on the same system the sorting code is running on. strtotime("15:30") returns a unix timestamp for today's date at 3:30pm.
Andrew
+2  A: 

The uksort function sorts the array by keys while usort sorts the array by value and your array to be sorted is acctualy:

$to_sort = array( 
                  0 => array("time"=>"12:15", "date"=>"2009-03-24"),
                  1 => array("time"=>"12:10", "date"=>"2009-03-23"),
                  2 => array("time"=>"12:00", "date"=>"2009-03-24"),
                  3 => array("time"=>"11:30", "date"=>"2009-03-24")
                );

Do you see the difference? :)

Ch4m3l3on
Yeesh... Did I really just ask everyone on the Internet why I'm an idiot? Thanks for being kind. I don't know why I couldn't figure that out yesterday. For some reason, I saw the example on the php docs and saw the keys ("the earth", "an apple", etc.) as values.
Andrew
Don't worry, sometimes it happens to miss something like that and that's when sites like this one come in handy. I'm glad that I could help :).
Ch4m3l3on