How to Write a Custom Comparator in Python


Generally, you want to use the built-in sorted() function which takes a custom comparator as its parameter. We need to pay attention to the fact that in Python 3 the parameter name and semantics have changed.

How the custom comparator works

When providing a custom comparator, it should generally return an integer/float value that follows the following pattern (as with most other programming languages and frameworks):

  • return a negative value (< 0) when the left item should be sorted before the right item
  • return a positive value (> 0) when the left item should be sorted after the right item
  • return `` when both the left and the right item have the same weight and should be ordered “equally” without precedence

The challenge

Write a comparator for a list of phonetic words for the letters of the greek alphabet.

A comparator is:

a custom comparison function of two arguments (iterable elements) which should return a negative, zero or positive number depending on whether the first argument is considered smaller than, equal to, or larger than the second argument

(source: https://docs.python.org/2/library/functions.html#sorted )

The greek alphabet is preloded for you as greek_alphabet:

greek_alphabet = (
    'alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta', 
    'eta', 'theta', 'iota', 'kappa', 'lambda', 'mu', 
    'nu', 'xi', 'omicron', 'pi', 'rho', 'sigma',
    'tau', 'upsilon', 'phi', 'chi', 'psi', 'omega')

Examples

greek_comparator('alpha', 'beta')   <  0
greek_comparator('psi', 'psi')      == 0
greek_comparator('upsilon', 'rho')  >  0

Test cases

test.expect(greek_comparator('alpha', 'beta') < 0, "result should be negative")
test.assert_equals(greek_comparator('psi', 'psi'), 0)
test.expect(greek_comparator('upsilon', 'rho'), "result should be positive")

The solution in Python

Option 1 (using index):

def greek_comparator(lhs, rhs):
    return greek_alphabet.index(lhs) - greek_alphabet.index(rhs)

Option 2 (using cmp):

def greek_comparator(lhs, rhs):
    return cmp(greek_alphabet.index(lhs), greek_alphabet.index(rhs))

Option 3 (using map/reduce):

def greek_comparator(*args):
    return reduce(int.__sub__, map(greek_alphabet.index, args))