How to Compare Keys of Different Types in Python
In Python 3, strong typing rules prevent direct comparison between different data types. While Python 2 allowed you to compare an integer to a string (e.g., 1 < "a"), Python 3 raises a TypeError: '<' not supported between instances of 'int' and 'str'.
This behavior protects developers from logical errors, but it presents a challenge when sorting lists with mixed data types or organizing dictionaries with heterogeneous keys. This guide explains how to safely compare and sort mixed-type keys using type conversion and custom key functions.
Understanding the TypeError
Python 3 does not define a default ordering between different types. If you attempt to sort a list containing both integers and strings, or check if an integer key is greater than a string key, the operation fails.
# A list containing integers and strings
mixed_data = [10, 'apple', 5, 'banana']
try:
# ⛔️ Incorrect: Direct sorting fails in Python 3
sorted_data = sorted(mixed_data)
print(sorted_data)
except TypeError as e:
print(f"Error: {e}")
Output:
Error: '<' not supported between instances of 'str' and 'int'
Why does this happen? Python cannot logically determine if the number 5 is "smaller" than the word "apple". To resolve this, you must provide a rule (a key) that tells Python how to compare them.
Method 1: String Conversion (Simple Sort)
The simplest way to compare mixed types is to convert everything to a string temporarily during the comparison. This uses the lexicographical (dictionary) order.
Using key=str
The sorted() function and list.sort() method accept a key argument. By passing str, Python converts every item to a string before comparing.
mixed_data = [10, 'apple', 2, 'banana', 100]
# ✅ Correct: Sort based on string representation
sorted_data = sorted(mixed_data, key=str)
print(f"Original: {mixed_data}")
print(f"Sorted: {sorted_data}")
Output:
Original: [10, 'apple', 2, 'banana', 100]
Sorted: [10, 100, 2, 'apple', 'banana']
Lexicographical Pitfall: Notice that 10 comes before 2 in the output above. In string comparison, character "1" comes before character "2". If you need numeric sorting for numbers, this method is insufficient.
Method 2: Tuple Grouping (Type-Aware Sort)
If you want to sort items such that all Integers come first (sorted numerically), followed by all Strings (sorted alphabetically), you can use a tuple key.
Python compares tuples element-by-element. We can create a key that returns: (type_name, value).
- Type Name: Groups items by type (e.g., "int" comes before "str").
- Value: Sorts the actual items within their type groups.
mixed_data = [10, 'apple', 2, 'banana', 100]
# ✅ Correct: Sort by type name first, then by value
# We use str(x) for the second element to ensure the second elements
# are comparable even if types differ in edge cases, strictly speaking
# the type separation usually prevents direct comparison of the second element across types.
def type_sort_key(item):
return (type(item).__name__, item)
# Sort
sorted_data = sorted(mixed_data, key=type_sort_key)
print(f"Sorted: {sorted_data}")
Output:
Sorted: [2, 10, 100, 'apple', 'banana']
Explanation:
- Integers are converted to keys like
('int', 2),('int', 10). - Strings are converted to keys like
('str', 'apple'). - Since
'int'comes before'str'alphabetically, all numbers appear before words.
Method 3: Safe Numeric Conversion
Sometimes keys are of different types (string and int) but represent the same concept (numbers). For example, a dictionary might contain 1 (int) and "5" (string). You might want to compare them numerically.
You can write a custom function that attempts to convert everything to a float, and falls back to string comparison if that fails.
mixed_numbers = [10, "2", 5, "1.5", "apple"]
def safe_numeric_key(item):
try:
# Try to treat it as a number
return (0, float(item))
except (ValueError, TypeError):
# Fallback: treat as a string, put it after numbers (1)
return (1, str(item))
# ✅ Correct: "2" and "1.5" are treated as numbers
sorted_nums = sorted(mixed_numbers, key=safe_numeric_key)
print(f"Sorted: {sorted_nums}")
Output:
Sorted: ['1.5', '2', 5, 10, 'apple']
This strategy uses tuple sorting again. The first element (0 or 1) ensures all convertable numbers appear before non-number strings.
Conclusion
To compare keys of different types in Python:
- Use
key=strif you just need a quick, crash-free sort and don't care about numeric order (e.g.,10before2). - Use
key=lambda x: (type(x).__name__, x)if you want to group items by type (e.g., all numbers first, then all strings). - Use a try-except wrapper if you need to interpret strings as numbers dynamically.