-1

Before anyone says 'try Google', I've already done that plus searched php.net for a solution :)

So here is my issue. I have a rather complex multi-dimensional array which is being produced by a method in a class that carries out a levenshtein based matching algorithm upon passed data to a table of existing data. Here is an example of how the array would look:

[6976989] => Array
    (
        [recid] => 4
        [appid] => 
        [loanid] => 6976989
        [import_name] => Joe Bloggs
        [import_postcode] => BL0 G55
        [import_email] => blahh@blahhh.co.uk
    )

[32424] => Array
    (
        [recid] => 5
        [appid] => 345
        [loanid] => 32424
        [import_name] => Henry Hill
        [import_postcode] => BS5 1GH
        [import_email] => thisis@myemail.com
        [matches] => Array
            (
                [5] => Array
                    (
                        [appid] => 345
                        [match_name] => Henry Hall
                        [match_postcode] => BS5 1GH
                        [match_email] => thisis@myemail.com
                    )

            )

    )

The array will basically find close matches from the data passed in from a third party company and then use this result on a CRM interface for the client to approve or reject the matches presented.

That's how it works - and it works well. However, the issue is that some of the data passed to the table is completely different to any data existing (in the case of Joe Bloggs above) and so there is no match array to offer the user. The way we can tell this is that the [appid] is blank (this is the id which matches the first returned match). If the appid is blank or NULL then I need this to appear at the bottom of the interface. I've tried doing a usort() on the appid value but I'm not very experienced with array sorting in this way and whatever I do and whatever suggestions offered by php.net I use I cannot get the result I need.

Sorry if all this is a long-winded explanation but I thought it best to be specific. So if anyone has any ideas on how to do this, I would be very grateful.

Thank you in advance,

Michael

1 Answers1

1

This is a standard case of sorting an array with a custom comparison function which has already been covered too many times.

The only distinctive characteristic in this case is that you want nulls and blanks (empty strings?) to compare larger than any numeric value. So just program that into your comparison function:

function compareButEmptyIsLarger($x, $y)
{
    $isXEmpty = !strlen($x);
    $isYEmpty = !strlen($y);

    // Warning: this code tries to be clever at the expense of readability
    return $isXEmpty || $isYEmpty ? $isXEmpty - $isYEmpty : $x - $y;

    // If unsure how it works exactly it will be better to use longhand:
    // if ($isXEmpty && $isYEmpty) return 0; // two blanks are equal
    // else if ($isXEmpty) return 1;         // x is blank so "greater"
    // else if ($isYEmpty) return -1;        // y is blank so x is "lesser"
    // else return $x - $y;                  // numeric comparison
}

You can then integrate this function with any customizable comparison method. Using the code from my answer to a related question, you could do:

usort($data, make_comparer(['appid', SORT_ASC, 'compareButEmptyIsLarger']));

Or, for a standard-stuff-only version:

usort($data, 
      function($x, $y) { 
          returnCompareButEmptyIsLarger($x['appid'], $y['appid']);
      });

You can of course inline the logic for returnCompareButEmptyIsLarger into the comparison lambda for better performance, IMO at the expense of readability.

Community
  • 1
  • 1
Jon
  • 396,160
  • 71
  • 697
  • 768
  • Thank you, this works perfectly. I was aware that the comparison function has been covered, in fact I've seen examples on php.net - but I guess I couldn't quite work it into my own code correctly! Thanks again. – Michael Emerson Mar 12 '14 at 13:04