How can I check if two strings are anagrams of each other?
Asked Answered
E

27

14

I am trying to write a program that accepts two strings from the user:

s1 = input("Please enter a word:")
s2 = input("Please enter another word:")

How can I output True if the two are anagrams and False otherwise?


If you found this question from a search engine and want to look for possibly multiple anagrams within a list: it is possible, but not optimal to compare each pair of elements. Please see Using Python, find anagrams for a list of words for more specific advice.

Etiquette answered 20/2, 2013 at 21:58 Comment(1)
It's mostly about algorithms, not specific languages. And I'm not sure we provide full solutions to such questions here if you don't have anything to start with.Enzyme
C
5

You need to think through your conditional logic a bit more. The loop is on the right track, but if there is a letter in s1 that is NOT in s2, you should break out of this loop and print the "False" statement. Consider using a variable like all_s1_in_s2 = True and then setting that to false if you find a letter that doesn't match.

Some other tips:

  • for l in s1 will loop through string s1 giving you access to each letter in sequence as l - you don't need range or len at all

  • The if .. in statement can help test whether a letter exists in a string, e.g. if letter in mystring: is a valid statement and this could help you a lot, again not needing range or len

  • You should avoid using numbers in variable names where possible - better would be word_one and word_two, as an example

Corvette answered 20/2, 2013 at 22:7 Comment(0)
M
46

Why not just sort the strings?

>>> sorted('anagram')
['a', 'a', 'a', 'g', 'm', 'n', 'r']
>>> sorted('nagaram')
['a', 'a', 'a', 'g', 'm', 'n', 'r']
>>> sorted('anagram') == sorted('nagaram')
True
Moneymaker answered 20/2, 2013 at 22:12 Comment(0)
P
18

You can use the magic Counter from collections library. From documentation:

It is an unordered collection where elements are stored as dictionary keys and their counts are stored as dictionary values

So, you can initialize a Counter object with a string (a iterable) and compare with another Counter from a string

from collections import Counter

def is_anagram(str1, str2):
   return Counter(str1) == Counter(str2)
Polygamous answered 9/4, 2015 at 3:10 Comment(1)
I like this solution better than using sorted since it's clearer what's actually being done hereMcguinness
C
5

You need to think through your conditional logic a bit more. The loop is on the right track, but if there is a letter in s1 that is NOT in s2, you should break out of this loop and print the "False" statement. Consider using a variable like all_s1_in_s2 = True and then setting that to false if you find a letter that doesn't match.

Some other tips:

  • for l in s1 will loop through string s1 giving you access to each letter in sequence as l - you don't need range or len at all

  • The if .. in statement can help test whether a letter exists in a string, e.g. if letter in mystring: is a valid statement and this could help you a lot, again not needing range or len

  • You should avoid using numbers in variable names where possible - better would be word_one and word_two, as an example

Corvette answered 20/2, 2013 at 22:7 Comment(0)
F
3

To check if two strings are anagrams of each other using dictionaries: Note : Even Number, special characters can be used as an input

def anagram(s):
    string_list = []
    for ch in s.lower():
        string_list.append(ch)

    string_dict = {}
    for ch in string_list:
        if ch not in string_dict:
            string_dict[ch] = 1
        else:
            string_dict[ch] = string_dict[ch] + 1

    return string_dict



s1 = "master"
s2 = "stream"

a = anagram(s1)
b = anagram(s2)

if a == b:
    print "Anagram"
else:
    print "Not Anagram"
Foust answered 7/1, 2016 at 4:47 Comment(0)
C
3
def is_anagram(w1, w2):
    w1, w2 = list(w1.upper()), list(w2.upper())
    w2.sort()
    w1.sort()
    return w1 == w2
Cernuous answered 20/10, 2016 at 6:20 Comment(1)
Nice and concise. But why not end it with return w1 == w2?Needlework
N
1
>>> s1 = 'vivid'
>>> s2 = 'dvivi'
>>> s3 = 'vivid'
>>> def is_anagram(s1, s2):
...     if s1.lower() == s2.lower():
...         return False
...     return sorted(s1.lower()) == sorted(s2.lower())
...
>>> is_anagram(s1, s2)
True
>>> is_anagram(s1, s3)
False
>>> s2 = 'dvivii'
>>> is_anagram(s1, s2)
False
>>> s2 = 'evivi'
>>> is_anagram(s1, s2)
False
>>> 
Numbers answered 12/8, 2014 at 22:33 Comment(1)
for the isAnagram function, you could just return the evaluated expression i.e return sorted(s..) == sorted(s2)Quote
S
1

    #An anagram is the result of rearranging the letters of a word to produce a new word. Anagrams are case insensitive
    #Examples:
    # foefet is an anagram of toffee
    # Buckethead is an anagram of DeathCubeK

    # The shortest my function style *************************************** 
    def is_anagram1(test, original):
        """Сhecks 'test' is anagram of 'original' strings based on:
        1. length of the both string and length of the sets made from the strings is equivalent
        2. then checks equivalents of sorted lists created from test and original strings

        >>> is_anagram1('Same','same')
        False
        >>> is_anagram1('toffee','foeftt')
        False
        >>> is_anagram1('foefet','toffee')
        True
        >>> is_anagram1("Buuckk",'kkkcuB')
        False
        >>> is_anagram1('Buckethead','DeathCubeK')
        True
        >>> is_anagram1('DeathCubeK','Buckethead')
        True
        """
        # check the length of the both string
        if len(test) != len(original):
            return False

        # check is the strings are the same
        t,o = test.lower(), original.lower()
        if t == o:
            return False

        # check the sorted lists
        return sorted(t) == sorted(o)


    # The final my one line code **************************************
    def is_anagram(test, original):
        """Сhecks 'test' is anagram of 'original' in one line of code

        >>> is_anagram('Same','same')
        False
        >>> is_anagram('toffee','foeftt')
        False
        >>> is_anagram('foefet','toffee')
        True
        >>> is_anagram("Buuckk",'kkkcuB')
        False
        >>> is_anagram('Buckethead','DeathCubeK')
        True
        >>> is_anagram('DeathCubeK','Buckethead')
        True
        """
        return False if len(test) != len(original) or test.lower() == original.lower() else sorted(test.lower()) == sorted(original.lower())

    if __name__ == "__main__":
        import doctest
        doctest.testmod(verbose=True)


### 2 items passed all tests:
### 6 tests in __main__.is_anagram
### 6 tests in __main__.is_anagram1
### 12 tests in 3 items.
### 12 passed and 0 failed.
### Test passed
Shadshadberry answered 31/5, 2016 at 22:40 Comment(0)
B
1

You could use the following code it will not count special characters nor it will count digits and will return "they are anagrams" if the total characters have occurred equally in both strings hence will tell the the strings are anagrams or not .

text = input('Enter a string: ')
text1 = input('Enter a string: ')
text,text1 = text.lower(),text1.lower()
count = 0
count1=0
for i in range(97,123):
    if chr(i) in text and chr(i) in text1:
    count1+=1
        if text.count(chr(i)) == text1.count(chr(i)):
             count +=1
if len(text) >= len(text1):
    num1 = len(text)
else:
    num1 = len(text1)
if count == count1:
    print("they are anagrams")
else :
    print("they are not anagrams")
Bout answered 3/12, 2017 at 8:23 Comment(0)
K
1

Here's a solution if you are adamant on using Python dictionary and you can't use functional programming:

Create a dictionary using comprehension and compare the dictionaries of the two word with a simple == operator.

def isanagram2(wrd1, wrd2):

    wrd1_dict = {k: 0 for k in wrd1}
    wrd2_dict = {k: 0 for k in wrd2}

    for c1, c2 in zip(wrd1, wrd2):
        wrd1_dict[c1] += 1
        wrd2_dict[c2] += 1

    if wrd1_dict == wrd2_dict:
        return True
    return False
Kautz answered 27/12, 2017 at 16:20 Comment(0)
E
1

I think we can get this like this


s1 = "listen"
s2 = "silent"
s1=list(s1);s1.sort()
s2 = list(s2);s2.sort()
if s1 == s2:
   print ("Given Strings are Anagram")
else:
   print ("Given String are not anagrams")

Earhart answered 26/2, 2019 at 4:35 Comment(0)
L
1

Not sure if it was proposed up there, but I went with:

def is_anagram(a, b):
    return sorted(a.lower()) == sorted(b.lower())
Labile answered 2/10, 2020 at 16:59 Comment(0)
G
0

Just a thought:

def check_(arg):
        mark = hash(str(set(sorted(arg))))
        return mark

def ana(s1, s2):
        if check_(s1) != check_(s2):
                pass
        elif len(s1) != len(s2):
                pass
        else:
             print("{0} could be anagram of  {1}".format(s1, s2))
Geest answered 26/2, 2015 at 11:29 Comment(0)
T
0

This worked for me

str1="abcd"
str2="bcad"
word1=[]
word2=[]
for x in range(len(str1)):
    word1.append(str1[x])
for x in range(len(str2)):
    word2.append(str2[x])
if(len(word1)==len(word2)):
    for letter in word1:
        if letter in word2:
            word2.remove(letter)

if len(word2)==0:
    print "anagram"
else:
    print "not anagram"
Thermobarometer answered 4/4, 2015 at 17:12 Comment(0)
F
0

Return True answers the question "Is w2 an anagram of a subsequence of w1"

Explanation: In the code below, we can answer two questions: 1) whether or not two strings are anagrams,2) If w2 is an anagram of a sub-sequence of w1. We use O(1) space (constant) and O(n) time. The dictionary d0 can be expanded to include any characters and we remain within O(1) space bound.

def anagrams(w1,w2):
       d0={chr(i):0 for i in range(ord('a'),ord('z'))}
       for char in w1:
           d0[char]+=1
       for char in w2:
           if d0[char]==0:
               return False
           else:
               d0[char]-=1
    return sum([d0[x] for x in d0])==0 #return True (for subseqence anagram)
Flummery answered 2/3, 2018 at 16:7 Comment(5)
Although your code snippet might solve the issue, you should describe what’s the purpose of your code (how it solves the problem). Furthermore, you might want to check stackoverflow.com/help/how-to-answerAdlar
Thanks for the comment: Anagrams is a very interesting problem from time and space complexity point: Sorting at best is O(n*log(n)) time. A better O(n) time and O(1) space is given by others above and also here. I added this for two reasons: (1.) It is easy to include all characters. (Just expand the span "ord('a'), ord('z') " to a wider range (remains O(1) space) and (2.) last line of code can be "return True" if we just want substring anagrams. (It was asked above, and I found no one answered it). sum=0 assure equality of w1 and w2 .Flummery
He meant in the answer. Your answer got flagged because it is "code only" and the automated systems will continue to flag it as it is still "code only"Eject
Thanks Matthew, I included "Summary" is that what is needed? Though I do not see the "summary" yet.Flummery
Ahmad and Mathew, thanks for your remarks. I added a long header as a description, but the flag is still -1. What is going on? Can you help please?Flummery
C
0

Simplest shortest solution

def anagram(word1, word2):
    return sorted(word1) == sorted(word2)

check

print(anagram("xyz","zyx"))
>>True

print(anagram("xyz","zyy"))
>>False
Caroncarotene answered 6/12, 2018 at 21:7 Comment(1)
This has already been suggested in 2013.Sober
U
0

Here's one typical assignment solution:

def anagram(s1, s2):
""" (str, str) -> bool

Return True if s1 and s2 are anagrams

>>> anagram(s1, s2)
True
"""
    s1 = s1.replace(" ", "")
    s2 = s2.replace(" ", "")

    s1_new = list(s1)
    s2_new = list(s2)

    if len(s1_new) == len(s2_new):
        dupe_found = True
        while dupe_found:
            dupe_found = False
            for i in s1_new:
                for j in s2_new:
                    if i == j:
                        s1_new.remove(i)
                        s2_new.remove(j)
                        dupe_found = True
                        break
                break
    return s1_new == s2_new
Ulcerate answered 8/6, 2019 at 8:15 Comment(0)
B
0
def anagram(a,b):
x=[]
y=[]
for i in a:
    if i!=' ': # This will ignore the spaces in the sentence
        x+=[i] # Adds only letters into a list and ignore the spaces
for i in b:
    if i!=' ':
        y+=[i]
if len(x)==len(y): # if length of two lists are not same, They are not anagrams anyway. So it directly returns False.
    for i in range(len(x)):
        for j in range(len(y)):
            if x[i].lower()==y[j].lower(): 
                y.pop(j) # If the letter matched between first and second list, that letter is poped from that list.
                break
    return len(y)==0 # If the given sentences are anagrams, all the letters are poped out from the second list and function returns True(as the lenght of the second list is 0. If not, function will return False.
return False

anagram(a,b)

Bend answered 26/6, 2020 at 12:45 Comment(1)
Just a quick note. This code actually returns True only if both group of words are present in each other. It also returns False if there is any extra letter in a group.Bend
R
0

Java Code for Anagram

static void anagram(String s1,String s2){
    if(s1.length()!=s2.length()){
        System.out.println("not anagram");
        return;
    }
    else{
        int []arr=new int[256];

        int size=s1.length();
        for(int i=0;i<size;i++){
            arr[s1.charAt(i)]++;
            arr[s2.charAt(i)]--;
        }
        for(int i=0;i<256;i++){
            if(arr[i]!=0){
                System.out.println("not anagram");
                return;
                }
        }
        System.out.println("anagram");
    }
    
}
Ric answered 25/7, 2020 at 9:21 Comment(0)
A
0

Here a solution using dict comprehension.

def is_anagram(s1, s2):
    return {c:s1.count(c) for c in s1} == {c:s2.count(c) for c in s2}
Allround answered 24/7, 2021 at 2:50 Comment(0)
T
0
class Solution(object):
    def isAnagram(self, s, t):
        
        s_dict = {}
        t_dict = {}
        
        if len(s) != len(t):
            return False
        else:
            for i in range(0, len(s)):
                if s[i] in s_dict:
                    s_dict[s[i]] +=1
                else:
                    s_dict[s[i]] = 1
                
                if t[i] in t_dict:
                    t_dict[t[i]] +=1
                else:
                    t_dict[t[i]] = 1
        
        
        return s_dict == t_dict
Trichinize answered 19/4, 2022 at 18:53 Comment(0)
P
-1

Anagrams are the two different words formed with same characters: For eg: EAT and TEA likewise there can be numerous examples.

One good way to see if give two words or sentences are anagrams is to set a counter array of size 256, and initially set all the values to 0. (This can be a good option if the input is bigger, at least than a few words) Now start reading the first string(word or a sentence), and increment its corresponding ASCII location in the array by one. Repeat this for the complete string. Now start reading the second string and keep decreasing the corresponding ASCII counter of each letter in the array. Finally, parse the array; if all the values are zero then the inputs were anagrams otherwise not. Following is the commented code for the better understanding.

#include<iostream>
#include<string>

using namespace std;

bool is_anagram(string s1, string s2)
{
    //Following statement chechs the base condition; if either of the strings is empty,                                  
    //return False
    if(s1.length() == 0 || s2.length() == 0)
        return false;

    //initializing the counter array and setting it's values to 0
    int counter[256] = {0};

    //Calculating the lengths of both the strings
    int len1 = s1.length();
    int len2 = s2.length();

    //Following is also a base condition that checks whether the strings are equal in 
    //length, if not we return False
    if(len1 != len2)
        return false;

    //Following for loop increments the values of the counter array for the first  
    //string
    for(int i = 0; i < len1; i++)
    {
        counter[s1[i]]++;
    }

    //This for loop decrements the values of the counter array for the second string
    for(int i = 0; i < len2; i--)
    {
        counter[s2[i]]--;
    }
    //Now we check whether the counter array is empty/(or as it was initialized); if               
    //yes then the two strings are anagrams
    for(int i = 0; i < 256; i++)
    {
        if(counter[i] != 0)
            return false;
    }

    return true;
}
Palladin answered 14/5, 2013 at 22:25 Comment(2)
I guess the first If should be if(s1.length() == 0 || s2.length() == 0). As you cannot compare string with integer.Godhood
The question is tagged with python, this looks a lot like c++ to meMcguinness
R
-1

This case we check using two containers for each sorted string.

def anagram(s1, s2):
    str1 = ''
    str2 = ''

    for i in s1:
      str1 += i

    for j in s2:
      str2 += j

    if str1 == str2:
      return True

    return False
Reddick answered 2/1, 2019 at 15:13 Comment(0)
U
-1
str1='ohaha'
str2='hahao1'
set3=set(str1)
set4=set(str2)
if(len(set3.difference(set4))==0 and len(set4.difference(set3))==0):
     print('anagrams')
else:
     print('not anagrams')
Unreserved answered 10/11, 2019 at 20:35 Comment(2)
Hello to SO @Sai Sudha! Your answer looks correct, but please provide some context/explanation to your code. Also please tell us what language did you used. If it's Python you don't need parenthesis in your if condition. Moreover you don't need to check the difference length explicitly. bool(set3 - set4) or not not (set3 - set4) should work for you.Victorvictoria
If you're going to answer a 6 year old question that already has 20 answers, it would be a good idea to introduce your answer and not just supply code. In this case, however, your answer does't work as it doesn't take into account how many of each character there are. Just using sets in this way your code says that hahao and ohahahahahahahahaha are anagrams, which they are not.Disagreeable
D
-2

Just another solution without using sort:

s1 = "aaabbbccc"
s2 = "abcabcabc"

def are_anagram1(s1, s2):
   return [False, True][sum([ord(x) for x in s1]) == sum([ord(x) for x in s2])]

print are_anagram1(s1,s2)

NB: this works only for alphabet not numerals

Diacid answered 12/1, 2014 at 6:39 Comment(5)
return sum(map(ord, s1)) == sum(map(ord, s2)) should also workSuperheat
Ya sure, s1 and s2 are iterable, thank you thats make it more shorter,Diacid
how about sum(map(ord, "bbf")), sum(map(ord, "acf")), does this two string is anagram?Skirting
It doesn't work for the case s1 = "ad", s2 = "bc". sum of Ascii is same (197), but "ad" and "bc" are NOT Anagrams.Godhood
Like mentioned in other comments, this method doesn't work as different group of characters can give the same sum result.Outcross
R
-2

I think the shortest way can be:

are_anagrams = lambda str1, str2: sorted(str1) == sorted(str2)

result = are_anagrams("debit card",  "bad credit")
print(result)
Rob answered 8/2, 2019 at 19:12 Comment(2)
this only works if one string is reverse of the otherDisqualify
This checks for palindromes, not anagrams.Phatic
D
-2
def areAnagram(s1,s2):
    if len(s1) != len(s2):
        return False
    count = [0]*256
    for i in range(len(s1)):
        count[ord(s1[i])] += 1
        count[ord(s2[i])] -= 1
                       
    for x in count:
        if x != 0: 
            return False
    return True

a = input("Enter a string:")
b = input("Enter b string: ")

print(areAnagram(a,b))
Dawna answered 23/6, 2021 at 11:57 Comment(1)
While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.Frequent
B
-2

Solution:

print('Strings are anagrams' if sorted(input("Enter 1st string: "))== sorted(input("Enter 2nd string: ")) else 'Strings are not anagrams')
Bjork answered 17/8, 2021 at 9:41 Comment(3)
Welcome to Stack Overflow! Please make sure that your solution was not already proposed in the one of the other answers before posting it.Agulhas
@SergeyShubin I wrote the Optimized code of the code given here. To show how I optimized it I wrote the code which is not Copied. But then I also made the changes now it's the code that doesn't match any of the code here!!Bjork
You may explain in your answer why is it better than others: it is highly encouraged to comment solutions for other visitors for better understanding. Does it run faster? Or consume less memory? Or more stable (works in some border cases that other algorithms process incorrect)?Agulhas

© 2022 - 2024 — McMap. All rights reserved.