Search code examples
sortingmathlanguage-agnostictheory

user defined sorting functions, how to properly use them?


I have always used this method for accomplishing this kind of sort, but doesn't look correct to me

usort($array, function($team1, $team2){

    $t1 = ($team1->points * 1000) + ($team1->goalsFor - $team1->goalsAgainst);
    $t2 = ($team2->points * 1000) + ($team2->goalsFor - $team2->goalsAgainst);

    if($t1 == $t2) return 0;
    return $t1 > $t2 ? 1 : -1;
});

an alternative to this method is to use str_pad, which does nearly the same


basically what I do is to separate with zeros the sorting subjects

$t1 = 32008; // 32 points with a GD of 8
$t2 = 32003; // 32 points with a GD of 3

but what if a team got a weird goals difference?

$t1 = 32008; // 32 points with a GD of 8
$t2 = 33000; // 32 points with a GD of 1000

clearly this can't happen, but it's an example

is this a good way? how about the 32-64 bit / floating numbers [im]precision limits?

does someone have suggestions for this?

thank you :)


feel free to improve the title


Solution

  • A better approach is this:

    function ($team1, $team2) {
        if ($team1->points != $team2->points) {
            return $team1->points > $team2->points ? 1 : -1;
        }
        $diff1 = $team1->goalsFor - $team1->goalsAgainst;
        $diff2 = $team2->goalsFor - $team2->goalsAgainst;
        if ($diff1 != $diff2) {
            return $diff1 > $diff2 ? 1 : -1;
        }
        return 0;
    }
    

    Or, in Java (using Guava), I'd write it like this:

    public int compare(Team team1, Team team2) {
        return ComparisonChain.start()
                .compare(team1.getPoints(), team2.getPoints)
                .compare(team1.getGoalsFor() - team1.getGoalsAgainst(),
                         team2.getGoalsFor() - team2.getGoalsAgainst())
                .result();
    }
    

    Clearly, PHP doesn't have ComparisonChain, but it shouldn't be hard to implement.