10
\$\begingroup\$

I see a couple of these on codereview but I was hoping my way hasn't yet been encountered:

def is_palindrome_permutation(strng):
 cache = set()
 for char in strng.lower():
 if not char.isalpha():
 continue
 if char in cache:
 cache.remove(char)
 else:
 cache.add(char)
 return len(cache) <= 1

Instead of maintaining any counts of characters to check for oddness or evenness, simply add and remove characters from a set. A character repeated an even number of times will be removed from the set; a character repeated an odd number of times will remain in the set. If the final set has a length less than or equal to one, it is a permutation of a palindrome.

200_success
146k22 gold badges190 silver badges479 bronze badges
asked Oct 22, 2016 at 5:42
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I would call the function is_anagram_of_palindrome. Does it handle utf-8 or just a..z? You might want to state in a comment what you consider legal characters. \$\endgroup\$ Commented Oct 22, 2016 at 18:08

2 Answers 2

15
\$\begingroup\$

Documentation

You should definitely add a docstring. It took me a few seconds to figure out was was going. Make sure to add some examples in the docstring as well.

Naming

The name cache may not be the best name. Why? Let's look at the definition of cache:

is a hardware or software component that stores data so future requests for that data can be served faster

I don't really believe you use cache to serve stuff faster. I believe odd_occuring_letters is a better idea. (I don't like long names, maybe challenge yourself to a shorter name? Maybe odd_letters? Think about it.)

(More) Comments

Even then, odd_occuring_letters isn't the most descriptive name, so you should include some comments as to what your code does. Don't over do it though.

Remember saying something like:

# Check the length of odd_occuring_letters is less than or equal to one.
return len(odd_occuring_letters) <= 1 

Is not good. But saying:

# A word can have at most 1 odd character and still be palindrome.
return len(odd_occuring_letters) <= 1

explains to me why you return the length compared to one.

answered Oct 22, 2016 at 6:25
\$\endgroup\$
6
\$\begingroup\$

You can take advantage of the set.symmetric_difference_update() operation, which does exactly your conditional add/remove.

def is_palindrome_permutation(s):
 unpaired_chars = set()
 for char in s.lower():
 if char.isalpha():
 unpaired_chars ^= set(char)
 return len(unpaired_chars) <= 1
answered Oct 22, 2016 at 18:20
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.