Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Check for Anagrams Using Python

DZone 's Guide to

How to Check for Anagrams Using Python

How many lines did we write again?

· Web Dev Zone ·
Free Resource

In this journey to become a somewhat competent and capable Python programmer, I've come to realize that we don't know what we don't know. There is and will always be a better way of doing things. But as budding programmers, it's important that we don't get discouraged when a problem seems too difficult because most of the time, the solution is staring us right in the face. When that happens, just take a breath and step away from your computer, rest your eyes, and maybe have some of your favorite brain tea. Then get back to it because the problem won't solve itself, and the world needs people like you to make a difference.

Okay, I'm done with my rant.

Today, we're going to cover how to check for anagrams in Python. If you don't know what an anagram is, it's a word, phrase, or name formed by rearranging the letters of another, such as cinema, formed from iceman.

The project that we'll be working on comes from user Sandbochs of CodeWars. If you haven't realized from any of my previous posts, I really enjoy their projects and exercises. I highly recommend checking them out if you're serious about learning software development. 

On to the problem.

Our task is to write a function that will find all the anagrams of a word from a list. We will be given two inputs, a word and an array with words. The result should be a list of all the anagrams or an empty list if there are none. For example:

anagrams('abba', ['aabb', 'abcd', 'bbaa', 'dada']) => ['aabb', 'bbaa']

anagrams('racer', ['crazer', 'carer', 'racar', 'caers', 'racer']) => ['carer', 'racer']

anagrams('laser', ['lazing', 'lazy',  'lacer']) => []


Seems simple enough right? Let's break this down.

Where Do We Start?

There a few ways that we can go about handling this, but what we're going to do is keep things really simple to start off.

  • First, we'll split our single word into a list.
  • Next, using Regular Expressions we identify our pattern in the array of words.
  • Then, using the Counter module we will compare the order and value of our single word list and each matched item.
  • Finally, we'll append the matched values, join them back together in the same order and return our result.

As you can tell, it's pretty straight forward once you have your steps written out. Let's begin.

def anagrams(word,words):
    import re 
    from collections import OrderedDict, Counter
    result = []


We start off by defining our function with the two arguments, word and words. Next, we import our collections library and create an empty list for our result.

split_word = [i for i in word]


Since our single word is a string, we split it up into a list for easy comparison.

r = re.compile('[a-zA-Z]')
match = [r.findall(i) for i in words]


By using regular expressions in this way, we change the list of words that each match the format of our single word list while staying in the same order. This makes for easy comparison.

for item in match:
    if Counter(split_word) == Counter(item):
        result.append(''.join(item))


To Use or Not to Use Counter

Let's talk about the Counter method for a second. According to the Python Documentation page, a Counter is a dict subclass for counting hashable objects. By hashable, we mean that the objects can be used as dictionary keys. Counter is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values. As a result, counts are allowed to be any integer value, including zero or negative counts.

Now, let's look at a quick example.

>>> from collections import Counter
>>> word = ['d', 'a', 'b', 'a', 'b']
>>> Counter(word)
Counter({'a': 2, 'b': 2, 'd': 1})


As you can see, using the Counter method, we were able to create key and value pairs for the unique elements as well as the number of occurrences. How convenient! Ok back to our problem.

for item in match:
    if Counter(split_word) == Counter(item):
        result.append(''.join(item))
return result


Using the Counter method in conjunction with our regular expression, we check to see if both lists of words are identical in value, order, and quantity. If our query returns true, the list is appended to our result list and joined back together. Now, let's run the code and see if it works.

print(anagrams('aabba' ,['ababa','bbaaa','dabab','aabab']))
>>>['ababa', 'bbaaa', 'aabab']


Great! We queried all of the words in the given list and returned the items that matched our single word perfectly.

Now, I did promise you an easier and potentially quick way to perform the same task. Don't be upset when you see the result. To be honest I was a bit heartbroken when I came across it as well.

Let's take a look.

from collections import Counter


Using this method we decide not to use Regular Expressions but instead to focus on the Counter method.

def anagramsV2(word,words): return [w for w in words if Counter(word) == Counter(w)]


You're probably thinking, "Drae are you serious? We literally could have solved this in two lines of code?" To that I say yes....but wait, there's more.

def anagramV3(word,words): return [item for item in words if sorted(item) == sorted(word)]


Before I move on, let's talk about this infamous sorted method. So, sorted is a built-in method (which is a testament as to why it's so easy to forget about) in the Python library that returns a sorted list from the iterable.

For example:

>>> phrase = 'pytechcoding'
>>> sorted(phrase)
['c', 'c', 'd', 'e', 'g', 'h', 'i', 'n', 'o', 'p', 't', 'y']


Based on the arguments that you include, you can alter the order of your results. Just make sure you don't mix and match strings with other objects; that won't work. 

Conclusion

That's right. We could have solved the entire problem with one single line of code. I decided to show it to you like this for two reasons. One is because I wanted to share my pain. I literally spent a good 15 minutes looking at that one line thinking, "Are you serious???" The second reason was to solidify your understanding of the fact that no matter how good you think you are, there will always be someone that knows a little bit more. That's why it's important to keep pressing forward and keep learning more.

Muhammad Waseem said, "Give a man a program, frustrate him for a day. Teach a man to program, and frustrate him for a lifetime." I won't say that it will get easier the longer you continue to write code, but your understanding and way of thinking through a problem set will greatly improve.

If you found value in this article please leave a comment and share on your favorite social media outlet. I want to hear some of your input. Is there a project that you'd like to see or a topic that's been giving you a hard time? Thanks so much for your support. Until next time!

Topics:
python 3.7.0 ,puzzles ,sorted array ,regular expression ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}