-3

I have got the following data:

[
  {
    "status": {
      "notAfter": "2020-12-12T04:41:24Z"
    }
  },
  {
    "status": {
      "notAfter": "2022-03-30T21:20:33Z"
    }
  },
  {
    "status": {
      "notAfter": "2022-04-19T22:48:22Z"
    }
  },
  {
    "status": {}
  },
  {
    "status": {}
  }
]

I'm sorting this data using a usort custom function, which sorts them by status.notAfter, however sometimes notAfter could be missing, I need these items at the top of the sorted array.

Below is the code I have got, however this does not work, the data sorting is correct, however the ones with the missing data are not at the top or bottom.

usort($data, static function($a, $b) {
    if (!array_key_exists('notAfter', $b['status']) || !array_key_exists('notAfter', $a['status'])) {
        return 1;
    }
    $ad = new \DateTime($a['status']['notAfter']);
    $bd = new \DateTime($b['status']['notAfter']);
    
    if ($ad == $bd) {
        return 0;
    }
    return $ad < $bd ? -1 : 1;
});
Martyn Ball
  • 4,679
  • 8
  • 56
  • 126
  • How does this question not meet the guidelines? I have got a problem and provided example data, and the code I have at the moment... If you vote to close then leave a comment explaining, else your contribution is void and pointless. – Martyn Ball Aug 19 '22 at 11:32
  • 1
    `return 1;` in your first if there makes no sense - returning 1 means, $a is supposed to be considered greater than $b. So whenever _either one_ of them it missing that value, you _always_ say the first one should be considered the greater one. – CBroe Aug 19 '22 at 11:32
  • @CBroe i'm guessing i'm understanding how `usort` works incorrectly then. My understanding was that if I checked `a` and `b` had the key, and if not then return `1` this would move the item higher up in the array. – Martyn Ball Aug 19 '22 at 11:34
  • 1
    The return value only decides, whether $a should be considered less, equal or greater than $b. So if $a is missing the property, but $b has it - then you need to return -1, to make $a come before $b in the final result. If $a has it, and $b doesn't - then you need to return 1. And if the both have it or are both missing it - then you need to _continue_ comparing them, by your secondary comparison criterion. – CBroe Aug 19 '22 at 11:37
  • @CBroe Ah okay i get it now thank you I have fixed my code, not sure if you want to stick this as an answer? – Martyn Ball Aug 19 '22 at 11:39
  • Made an answer out of the two main comments, that enough, or should I add anything more in terms of explanation? – CBroe Aug 19 '22 at 11:43
  • Your entire data structure is "Big-endian" so [`sort()` does everything that you need with no fooling around needed](https://3v4l.org/DIVtb). – mickmackusa Aug 29 '22 at 02:02

1 Answers1

1

return 1; in your first if there makes no sense - returning 1 means, $a is supposed to be considered greater than $b. So whenever either one of them is missing that value, you always say the first one should be considered the greater one.

The return value of the callback function only decides, whether $a should be considered less, equal or greater than $b. So if $a is missing the property, but $b has it - then you need to return -1, to make $a come before $b in the final result. If $a has it, and $b doesn't - then you need to return 1. And if the both have it or are both missing it - then you need to continue comparing them, by your secondary comparison criterion.

CBroe
  • 91,630
  • 14
  • 92
  • 150