Write a Python palindrome check that ignores case and non-alphanumeric characters.
A palindrome reads the same forwards and backwards once you settle what counts as a character. The usual definition for a phrase ignores case, spaces and punctuation.
def is_palindrome(text):
cleaned = [char.lower() for char in text if char.isalnum()]
return cleaned == cleaned[::-1]
print(is_palindrome("A man, a plan, a canal: Panama")) # True
print(is_palindrome("hello")) # False
print(is_palindrome("No lemon, no melon")) # TrueThe function does three things: it keeps only alphanumeric characters, it lowercases them so the comparison is case-insensitive, and it compares the cleaned list with its reverse.
Two details worth explaining. The isalnum test is what removes punctuation and spaces, and it is Unicode-aware, so accented letters are kept rather than stripped. And the comparison uses a list rather than the original string, because once you have removed the punctuation the sequence of characters is what matters, not the spacing.
There is a faster variant that avoids building the reversed copy: walk two pointers from each end of the cleaned list towards the middle and compare as you go. It does the same amount of work asymptotically but uses constant extra space, which matters only if the input is very large.
The one-line version people sometimes give, comparing text with text[::-1], is only correct if you do not need to ignore anything. It also fails on the empty string in some naive implementations, because the empty string is trivially a palindrome and the check has to handle that case deliberately rather than by accident.