0

I got the following array:

 ["person41"]=>
array(2) {
  ["original"]=>
  string(29) "photo_1.jpg"
  ["confidence"]=>
  float(0.99999)
}
["person42"]=>
array(2) {
  ["original"]=>
  string(30) "original_photo_not_defined.jpg"
  ["confidence"]=>
  float(0.99998)
}
["person33"]=>
array(2) {
  ["original"]=>
  string(29) "photo_2018.jpg"
  ["confidence"]=>
  float(0.99998)
}
["person43"]=>
array(2) {
  ["original"]=>
  string(30) "original_photo_not_defined.jpg"
  ["confidence"]=>
  float(0.9995)
}
["person44"]=>
array(2) {
  ["original"]=>
  string(30) "original_photo_not_defined.jpg"
  ["confidence"]=>
  float(0.9996)
}

I need to sort it in order to (keys should be kept): 1st - show elements with defined original photo (original does NOT equal original_photo_not_defined.jpg), 2nd - all those with original_photo_not_defined.jpg should be sorted by confidence from 0.99999 first. So the final array should look like following:

["person41"]=>
array(2) {
  ["original"]=>
  string(29) "photo_1.jpg"
  ["confidence"]=>
  float(0.99999)
}
["person33"]=>
array(2) {
  ["original"]=>
  string(29) "photo_2018.jpg"
  ["confidence"]=>
  float(0.99998)
}
["person42"]=>
array(2) {
  ["original"]=>
  string(30) "original_photo_not_defined.jpg"
  ["confidence"]=>
  float(0.99998)
}
["person44"]=>
array(2) {
  ["original"]=>
  string(30) "original_photo_not_defined.jpg"
  ["confidence"]=>
  float(0.9996)
}
["person43"]=>
array(2) {
  ["original"]=>
  string(30) "original_photo_not_defined.jpg"
  ["confidence"]=>
  float(0.9995)
}

I tried this solution:

function cmp(array $a, array $b) {
    if (($cmp = strcmp($a['foo'], $b['foo'])) !== 0) {
        return $cmp;
    } else {
        return $a['baz'] - $b['baz'];
    }
}

but I'm not sure where to point that elements with original_photo_not_defined.jpg should be placed lower and how to sort by confidence then? Any ideas would be welcome, thank you.

Masha
  • 827
  • 1
  • 10
  • 30
  • Does this come from a database? If so, you should sort it in the query. – jeroen Oct 19 '18 at 11:39
  • no, this comes in json string from 3rd party service, no database – Masha Oct 19 '18 at 11:40
  • 1
    _“I tried this solution:”_ - well saying that you actually _tried_ anything with that might be a bit much, I think - because using the keys `foo` and `baz` with your data wouldn’t make sense to begin with. // The mentioned duplicate explains what your comparison function needs to do: Return a value based on the comparison of _two_ array elements passed to it. So you need to differentiate between the cases "a is orig, b isn’t", "a isn’t, but b is" first of all … – misorude Oct 19 '18 at 11:47
  • And only if the both are or both aren’t originals, then you look at the `confidence` of each. – misorude Oct 19 '18 at 11:48
  • @Masha btw, when comparing float values like 0.99999 you might get rounding errors. To prevent this you can cast those to string or use the `bccomp()` from the bcmath-extension. If you run into problems that a value seems like it is sorted the wrong way, this might be the cause. – dbrumann Oct 19 '18 at 12:35

1 Answers1

2

The comparison function can be a bit challenging:

uasort($data, function (array $a, array $b) {
    if (array_key_exists('name', $a) && $a['name'] != 'not_valid.png') {
        if (array_key_exists('name', $b) && $b['name'] != 'not_valid.png') {
            if ($a['confidence'] == $b['confidence']) {
                return 0;
            }

            return $a['confidence'] > $b['confidence'] ? -1 : 1;
        }
        return -1;
    } else if (array_key_exists('name', $b) && $b['name'] != 'not_valid.png') {
        return 1;
    }

    if ($a['confidence'] == $b['confidence']) {
        return 0;
    }

    return $a['confidence'] > $b['confidence'] ? -1 : 1;
});

Basically you have to return either 1, 0, -1 depending on whether one precedes or follows the other or both are on the same level. With uasort you will sort and keep the array key ("personXX" in your case).

The function then checks whether both have the requested key and value. If so, we have to compare their confidence. If one of them does not, we can already decide whether they are higher/lower. If both do not have the key, we have to again compare their confidence. You might have to adjust or bugfix, but generally this should point you in the right direction.

See: https://3v4l.org/3Hnbb

dbrumann
  • 16,803
  • 2
  • 42
  • 58