Skip to content

Instantly share code, notes, and snippets.

@pR0Ps
Last active August 29, 2015 14:10
Show Gist options
  • Save pR0Ps/1e1a1e892aad5b691448 to your computer and use it in GitHub Desktop.
Save pR0Ps/1e1a1e892aad5b691448 to your computer and use it in GitHub Desktop.
Do ordered comparisons with mixed types in Python 3 (good for sorting heterogeneous lists)
def compare(x, y):
if x == y:
return 0
try:
if x < y:
return -1
else:
return 1
except TypeError as e:
# The case where both are None is taken care of by the equality test
if x is None:
return -1
elif y is None:
return 1
# Compare by type name
if type(x) != type(y):
return compare(type(x).__name__, type(y).__name__)
elif isinstance(x, type):
return compare(x.__name__, y.__name__)
# Types are the same but a native compare didn't work, recursively compare elements
try:
for a, b in zip(x, y):
c = compare(a, b)
if c != 0:
return c
except TypeError:
raise e
return compare(len(x), len(y))
# Sorting example
if __name__ == '__main__':
from functools import cmp_to_key
l = ["str", str, int, dict, (None, 2), (0, 1), [None, None, None], (None, "str", None), (None, "str"), ["str", 2, None], 10, None, 5]
sl = sorted(l, key=cmp_to_key(compare))
print("Unsorted:\n{}".format(l))
print("Script output:\n{}".format(sl))
print("Python 2.7.8 output:\n[None, 5, 10, [None, None, None], ['str', 2, None], 'str', (None, 2), (None, 'str'), (None, 'str', None), (0, 1), <type 'int'>, <type 'dict'>, <type 'str'>]")
@mk-fg
Copy link

mk-fg commented Dec 4, 2014

L20 seem to have indentation error.

@mk-fg
Copy link

mk-fg commented Dec 4, 2014

Uhh.... and same probably goes for L23-L27 as well.
EDIT: nope, my bad, just L20.

@pR0Ps
Copy link
Author

pR0Ps commented Dec 4, 2014

Thanks, fixed (damn tabs)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment