Question

How might I sort the following using PHP? (where wed_2_open comes after wed_1_close)

I have the following JSON data:

"hours": {
  "mon_1_open": 406800,
  "mon_1_close": 437400,
  "tue_1_open": 493200,
  "tue_1_close": 523800,
  "wed_1_open": 579600,
  "wed_1_close": 590400,
  "thu_1_open": 61200,
  "thu_1_close": 91800,
  "fri_1_open": 147600,
  "fri_1_close": 178200,
  "sat_1_open": 237600,
  "sat_1_close": 264600,
  "sun_1_open": 324000,
  "sun_1_close": 345600,
  "wed_2_open": 597600,
  "wed_2_close": 619200
}

Which I then turn into a usable format using JSON_decode:

$obj=json_decode($json);

This is put into a loop to use convert it to HTML:

foreach ($obj->hours as $key => $val) {
    // Turn array items into HTML list items
}

From previous answers it seems like usort may be an answer, but I get errors telling me $obj is an object rather than an array.

Thanks.

Was it helpful?

Solution

Few notes:

  1. To use any of the array functions on the json_decode()ed data, you must pass true as the second parameter which gives you an associative array instead of an object.

  2. Whenever you plan to sort an array, look at this page which helps you decide which of the 12+ array sorting functions you should use.

Since the desired sorting is not intuitive (sorting by key puts friday on top and close before open) you should define a custom sorting function; use uksort() which allows you to do just that on array keys:

<?php
$data = json_decode('{"hours": {
    "mon_1_open": 406800,
    "mon_1_close": 437400,
    "tue_1_open": 493200,
    "tue_1_close": 523800,
    "wed_1_open": 579600,
    "wed_1_close": 590400,
    "thu_1_open": 61200,
    "thu_1_close": 91800,
    "fri_1_open": 147600,
    "fri_1_close": 178200,
    "sat_1_open": 237600,
    "sat_1_close": 264600,
    "sun_1_open": 324000,
    "sun_1_close": 345600,
    "wed_2_open": 597600,
    "wed_2_close": 619200
}}', true);

echo 'BEFORE ================================' . PHP_EOL;
print_r($data);

uksort($data['hours'], 'customsort'); 

echo 'AFTER  ================================' . PHP_EOL;
print_r($data);

function customsort($a, $b) {
    $tr_prefix = array(
        'mon' => 1,
        'tue' => 2,
        'wed' => 3,
        'thu' => 4,
        'fri' => 5,
        'sat' => 6,
        'sun' => 7
    );
    $tr_suffix = array(
        'open'  => 1,
        'close' => 2
    );
    $a = strtr(strtr($a, $tr_prefix), $tr_suffix);
    $b = strtr(strtr($b, $tr_prefix), $tr_suffix);
    return strcmp($a, $b);
}

Note: my customsort implementation shown above is vary naive. Improvise if necessary.

OTHER TIPS

$array = $json_decode($json,true);  //> tradyblix
ksort($array);                      //> Sort by keys

First off, your json is invalid as you're not placing curly brackets around the associative array that contains 'hours'. This might not be an issue if you've cut it out for brevity, but I had to change it when debugging.

More importantly, you can ask json_decode to convert the data in to an associative array instead of an instance of stdClass. ksort will then allow you to sort by keys.

$json = file_get_contents('jsonsort.txt');
$obj = json_decode($json, true);

var_dump($obj);
ksort($obj['hours']);
var_dump($obj);

You could have sorted by values with sort - usort is not needed unless you need to make a custom comparison function, say, comparing instances of objects.

You can then iterate and emit with this (escaping & markup added):

echo "<ol>\n";
foreach($obj['hours'] as $key => $val) {
        echo "\t<li>" . htmlentities($key) . ' => ' . htmlentities($val) . "</li>\n";
}
echo "</ol>\n";
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top