1

I want to check if two strings are anagrams. For example, if my word is "halo", I want to check if those letters appear in "loha". It should match because it's an anagram.

My attempt fails and I'm not sure why. My code and output is below. I have a list of words and I want to check to see which elements are anagrams in the list.

def anagram(myList):
    for elem in myList:
        chars = set(elem)
        if all((c in chars) for c in myList):
            print  "Yes, anagram ", elem, chars
        else:
            print "NOT anagram ", elem, chars


wordsList = ["halo", "loha", "ahlo", "sully"]
anagram(wordsList)

And here's my output

NOT anagram  halo set(['a', 'h', 'l', 'o'])
NOT anagram  loha set(['a', 'h', 'l', 'o'])
NOT anagram  ahlo set(['a', 'h', 'l', 'o'])
NOT anagram  sully set(['y', 's', 'u', 'l'])
buttHurtBuddy
  • 35
  • 1
  • 7
  • 1
    sets remove duplicates. Are you sure that's the kind of functionality you want? – cs95 Jan 31 '18 at 16:24
  • [`Counter`](https://docs.python.org/3/library/collections.html#collections.Counter)s are the best data structures for this – Patrick Haugh Jan 31 '18 at 16:26
  • @coldspeed No it's not, I forgot about that. What should I use instead? – buttHurtBuddy Jan 31 '18 at 16:26
  • Is the expected output yes if all words are anagrams of each other, and no other wise? Also, you can iterate strings as is (letter by letter is default). – kabanus Jan 31 '18 at 16:26
  • `c` takes the value `"halo"`, `"loha"` etc. Not individual characters. So `(c in chars)` is always false. – khelwood Jan 31 '18 at 16:27
  • @kabanus for now, I just want to see which words are anagrams of eachother. I'll group likely group anagrams later – buttHurtBuddy Jan 31 '18 at 16:28
  • 3
    Related/dupe: [Using Python, find anagrams for a list of words](https://stackoverflow.com/questions/8286554/using-python-find-anagrams-for-a-list-of-words) – pault Jan 31 '18 at 16:29
  • I suggest (in the pedagogical spirit) you first try to make a function that gets two words and returns whether those are anagrams. If you just want the answer that's fine also. Looks like @Pault got you started, I see now. – kabanus Jan 31 '18 at 16:30
  • 2
    _I want to check if two strings are anagrams_ If you only want to check two strings, why are you passing the entire word list to `anagram()`? – John Gordon Jan 31 '18 at 16:31
  • @JohnGordon The subproblem would be to check two strings. The bigger problem I'm trying to solve is checking in a list – buttHurtBuddy Jan 31 '18 at 16:43
  • Possible duplicate of [Using Python, find anagrams for a list of words](https://stackoverflow.com/questions/8286554/using-python-find-anagrams-for-a-list-of-words) – Jongware Feb 01 '18 at 10:19

7 Answers7

1

Try this

def isanagram(ele1,ele2):
    ele1=list(ele1)
    ele2=list(ele2)
    return(sorted(ele1)==sorted(ele2))

print(isanagram("ahlo", "halo"))

Out put

True

For multiple elements check

print(map(isanagram,["ahlo", "halo"],[ "alho", "sully"])

Out put

[True, False]

Artier
  • 1,648
  • 2
  • 8
  • 22
0

This should prove to be relatively fast in that it keeps a sorted list so it only has to make ONE new one every time it iterates.

from itertools import islice

def anagram(myList):
    s1 = sorted(myList[0])
    for i,elem in enumerate(islice(myList,1,len(myList))):
        s2 = sorted(elem)
        if s1 == s2:
            print ("Yes anagram: ",myList[i],elem)
        else:
            print ("Not anagram: ",myList[i],elem)
        s1 = s2

wordsList = ["halo", "loha", "ahlo", "sully"]
anagram(wordsList)

result:

Yes anagram:  halo loha
Yes anagram:  loha ahlo
Not anagram:  ahlo sully

Different structure option:

from itertools import islice

def is_anagram(sorted_1,sorted_2):
    if sorted_1 == sorted_2:
        return True
    return False

wordsList = ["halo", "loha", "ahlo", "sully"]

s1 = sorted(wordsList[0])
for i,elem in enumerate(islice(wordsList,1,len(wordsList))):
    s2 = sorted(elem)
    if is_anagram(s1,s2):
        print ("Yes anagram: ",wordsList[i],elem)
    else:
        print ("Not anagram: ",wordsList[i],elem)
    s1 = s2
ragardner
  • 1,836
  • 5
  • 22
  • 45
0

you can use counter which outputs a dictionary of letter counts for each letter in a word

from Collections import Counter

word1='halo'
word2='hola'

if Counter(word1) == Counter(word2):
   print 'Yes Anagram {} {}'.format(word1,word2)
else :
   print 'Not Anagram {} {}'.format(word1,word2)
Pratik Kumar
  • 2,211
  • 1
  • 17
  • 41
0

Simply use sorted() on both strings and compare them.

def is_anagram(str1, str2):
   return sorted(str1) == sorted(str2)

k = is_anagram('angel', 'glean')
if k == True:
   print('Strings are anagrams')
else:
   print('Strings are not anagrams')

Here, sorted('angel') outputs ['a', 'e', 'g', 'l', 'n'] and sorted('glean') also outputs ['a', 'e', 'g', 'l', 'n']. Both equal, hence are anagrams.

To make things clear:

>>> sorted('angel') 
['a', 'e', 'g', 'l', 'n'] 
>>> sorted('glean') 
['a', 'e', 'g', 'l', 'n'] 
>>> sorted('angel') == sorted('glean') 
True

Solution to your problem:

def is_anagram(str1, str2):
   return sorted(str1) == sorted(str2)

wordsList = ["halo", "loha", "ahlo", "sully"]
each = wordsList[0]
for another in wordsList:
   if each != another:
      k = is_anagram(each, another)
      if k == True:
         print('{} and {} are anagrams'.format(each, another))
      else:
         print('{} and {} are not anagrams'.format(each, another))

Output:

halo and loha are anagrams
halo and ahlo are anagrams
halo and sully are not anagrams
Austin
  • 25,759
  • 4
  • 25
  • 48
0

If you want to find all the angrams in your list, you might want to do this instead:

# Checks if two strings are anagrams
def isAnagram(str1, str2):
    return sorted(str1) == sorted(str2)

# Iterates over all items in your list and compares it with all other items to check if they are anagrams.
def anagrams(myList):
    for i in range(0,len(myList)):
        for j in range(i+1, len(myList)):
            if isAnagram(myList[i], myList[j]):
                print "Yes anagram: ", myList[i], myList[j]
            else:
                print "Not anagram: ", myList[i], myList[j]

wordsList = ["halo", "loha", "ahlo", "sully"]
anagram(wordsList)

This would return the following:

Yes anagram: halo loha
Yes anagram: halo ahlo
Not anagram: halo sully
Yes anagram: loha ahlo
Not anagram: loha sully
Not anagram: ahlo sully

This may not be the most efficient solution but it gets the job done.

Whooper
  • 575
  • 4
  • 20
0

Use sets:

set('hola')==set('loha')

outputs True

As noted in the comments, this will not work even with a len parameter attached. Here's a recursive anagram test to redeem myself

`def anagram(string1,string2):
if string1=='' or string2== '':
    if string1!='' or string2!='':
        return False
    else:
        return True
if len(string1)!=len(string2) or set(string1)!=set(string2):
    return False
stemp1 = list(string1)
stemp2 = list(string2)
stemp2.remove(stemp1[0])
return anagram(''.join(stemp1[1:]),''.join(stemp2))`
  • This fails for `set('marg')==set('grammar') >> True`. – Jongware Jan 31 '18 at 18:40
  • just put a parameter before like `if len('marg'')==len('grammar'):` or add it to the logical: `set('marg')==set('grammar') and len('marg')==len('grammar') >>false ` and boom universal anagram testing – Louis Barto Feb 01 '18 at 11:13
  • Nope. It would still not be able to tell the difference between `grammar` and `agmrrrr`. Read the [documentation on `set`](https://docs.python.org/3.6/library/stdtypes.html#set-types-set-frozenset) for the reason. – Jongware Feb 01 '18 at 11:25
  • 1
    I see the reason. You've bypassed the len parameter by making strings of the same len made up of different counts of characters. No need to read set docs but thanks. – Louis Barto Feb 01 '18 at 11:33
0

Below code takes a list of words as input and groups them into anagrams

def is_grouped(word, anagram_groups):
    is_grouped = False
    for group in anagram_groups:
        if word in group:
            print "{0} is already part of anagram group={1}".format(word, group)
            is_grouped = True
            break
    return is_grouped

def get_anagram_group(word_to_check, word_to_check_index, wordlist):
    word_to_check_as_list = list(word_to_check)
    word_to_check_as_list.sort()
    group = [word_to_check]
    for i in range(0, len(wordlist)):
        if not i == word_to_check_index:
            word = wordlist[i]
            word_as_list = list(word)
            word_as_list.sort()
            if word_as_list == word_to_check_as_list:
                group.append(word)   
    return group

def group_anagrams(wordlist):
    anagram_groups = []
    for i in range(0, len(wordlist)):

        word_under_test = wordlist[i]
        # check if the word's anagrams already identified as part of anagram group
        anagramed = is_grouped(word_under_test, anagram_groups)
        if not anagramed:
            # if word not already a part of anagram group then find find all anagrams for the word
            anagram_group = get_anagram_group(word_under_test, i, wordlist)
            if len(anagram_group) == 1:
                print "no anagrams found for word {0}".format(word_under_test)
            else:
                print "anagrams found for word {0}={1}".format(word_under_test, anagram_group)
                anagram_groups.append(anagram_group)
    return anagram_groups



wlist = ['aloha' , 'hoala', 'loaha', '123', '321', 'xya']
print group_anagrams(wlist)

output:

anagrams found for word aloha=['aloha', 'hoala', 'loaha']
hoala is already part of anagram group=['aloha', 'hoala', 'loaha']
loaha is already part of anagram group=['aloha', 'hoala', 'loaha']
anagrams found for word 123=['123', '321']
321 is already part of anagram group=['123', '321']
no anagrams found for word xya
[['aloha', 'hoala', 'loaha'], ['123', '321']]
satyakrish
  • 119
  • 5