AnagramsΒΆ

The string s1 is an anagram of string s2 if it contains the same letters, rearranged. We want to ignore case, and ignore spaces.

For example, "Praxis forever" and "A prefix rovers" are anagrams.

We'd like to write a function that returns True if the two arguments supplied to it are anagrams of each other.

We need a few functions:

str.isalpha()
    Return true if all characters in the string are alphabetic
    and there is at least one character, false otherwise.

str.count(sub)
    Return the number of non-overlapping occurrences of 
    substring sub in the range

str.lower()
    Return a copy of the string with all the cased characters 
    converted to lowercase

str.replace(old, new)
    Return a copy of the string with all occurrences of substring
    old replaced by new. 


Here is the first approach: convert both strings to lowercase, and then go through every letter that appears in either string, and make sure that the counts in s1 and s2 for that letter match.

In [1]:
def is_anagram(s1, s2):
    s1 = s1.lower() #Note: just going s1.lower() isn't
                    #enough, since s1.lower() returns
                    #a new string, but doesn't itself modify
                    #the string s1.
    s2 = s2.lower()
    
    for c in s1 + s2:
        #check that the counts match for every c
        if c.isalpha():
            if s1.count(c) != s2.count(c):
                return False
    return True

There is nothing that weird about the line for c in s1 + s2. Here, we are make a new string, s1 + s2, which is just s1 and s2 concatenating together. If we go through every character in s1 + s2, then we are going through every character that appears in either s1 or s2.

In [2]:
is_anagram("a prefix rovers", "praxis forever")    
Out[2]:
True

Here's another way: first, let's get rid of the spaces from s1 and s2. Then, let's sort all the characters in s1 and s2, alphabetically. Then, let's see if the results are the same. If they are the same, then s1 and s2 are anagrams.

Here's how these things work:

In [3]:
"a prefix rovers".replace(" ", "")
Out[3]:
'aprefixrovers'
In [4]:
sorted('aprefixrovers')
Out[4]:
['a', 'e', 'e', 'f', 'i', 'o', 'p', 'r', 'r', 'r', 's', 'v', 'x']
In [5]:
def is_anagram2(s1, s2):
    s1 = s1.lower().replace(" ", "")
    s2 = s2.lower().replace(" ", "")
    
    return sorted(s1) == sorted(s2)

What is s1.lower().replace(" ", "")? First, we create a new string, s1.lower(). Then, we create another new string, s1.lower() with the spaces removed. That's the value of s1.lower().replace(" ", "").

We can make the function one-liner like this:

In [6]:
def is_anagram2(s1, s2):
    return sorted(s1.lower().replace(" ", "")) == sorted(s2.lower().replace(" ", ""))