8

I am new to programming and right now i'm writing a league table in python. I would like to sort my league by first points, and if there are two teams with the same points I would like to sort them by goal difference, and if they have the same goal difference i would like to sort by name.

The first condition is pretty easy and is working by the following:

table.sort(reverse=True, key=Team.getPoints)

how do I insert the two following conditions?

3
  • You probably want to read the Python Sorting HowTo. (Actually, I'm having trouble loading it at the moment, but there's always Google Cache) Commented Jan 13, 2013 at 0:41
  • Wow. I have exactly same task: sort teams in league) Commented Apr 15, 2013 at 22:51
  • Possible duplicate of Sorting a Python list by two criteria Commented Jan 13, 2016 at 18:59

3 Answers 3

15

Have the key function return a tuple, with items in decreasing order of priority:

table.sort(reverse=True, key=lambda team: (Team.getPoints(team),
                                           Team.getGoalDifference(team),
                                           Team.getName(team))

Alternately, you could remember a factoid from algorithms 101, and make use of the fact .sort() is a stable sort, and thus doesn't change the relative order of items in a list if they compare as equal. This means you can sort three times, in increasing order of priority:

table.sort(reverse=True, key=Team.getName)
table.sort(reverse=True, key=Team.getGoalDifference)
table.sort(reverse=True, key=Team.getPoints)

This will be slower, but allows you to easily specify whether each step should be done in reverse or not. This can be done without multiple sorting passes using cmp_to_key(), but the comparator function would be nontrivial, something like:

def team_cmp(t1, t2):
    for key_func, reverse in [(Team.getName, True),
                              (Team.getGoalDifference, True),
                              (Team.getPoints, True)]:
        result = cmp(key_func(t1), key_func(t2))
        if reverse: result = -result;
        if result: return result
    return 0

table.sort(functools.cmp_to_key(team_cmp))

(Disclaimer: the above is written from memory, untested.) Emphasis is on "without multiple passes", which does not necessarily imply "faster". The overhead from the comparator function and cmp_to_key(), both of which are implemented in Python (as opposed to list.sort() and operator.itemgetter(), which should be part of the C core) is likely to be significant.

As an aside, you don't need to create dummy functions to pass to the key parameters. You can access the attribute directly, using:

table.sort(key=lambda t: t.points)

or the attrgetter operator wrapper:

table.sort(key=attrgetter('points'))
Sign up to request clarification or add additional context in comments.

6 Comments

Isn't the first a little different from the second? It applies reverse=True to the whole tuple, whereas the three-step version only applies it to the points.
@DSM It is, I was trying to make an example that you can change the order for the various steps, but I guess it's not obvious and confusing.
Well, couldn't you just use *-1 to reverse a field?
@SnakesandCoffee What if it's a string?
the function names seem to imply that they're numbers (except getName).
|
4

Sort the list by name first, then sort again by score difference. Python's sort is stable, meaning it will preserve order of elements that compare equal.

Comments

0

Python sorting algorithm is Timsort which, as ACEfanatic02 points out, is stable which means order is preserved. This link has a nice visual explanation of how it works.

1 Comment

And thus Tim Peters has become immortalised.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.