Reputation: 11
>> find_sub_anagram_in_wordlist('apple', ['ppl','al','app','apple'])
['ppl']
Why does the loop not add the other sub-anagrams?
Here is my code:
anagramList = []
def find_sub_anagram_in_wordlist(str, str_list):
global anagramList
anagramList.clear()
list1 = list(str)
list1.sort()
for word in str_list:
shouldAdd = True
listi = list(word)
listi.sort()
for j in listi:
if j in list1:
list1.remove(j)
else:
shouldAdd = False
if shouldAdd == True:
anagramList.append(word)
return anagramList
Upvotes: 1
Views: 65
Reputation: 5515
This line:
if j in list1:
list1.remove(j)
is your problem. Think about the first iteration of for word in str_list
where word == 'ppl
going through the following code with that in mind:
for j in listi: #for every char in word, 'p', 'p', 'l'
if j in list1: 'True for all three
list1.remove(j) 'removes all three letters
else:
shouldAdd = False
this leaves you with list1 == ['a','e']
. Your next iteration for word
gives you word == 'al'
. If we go through the above code again, you'll see that since there is no longer 'l'
in list1
, shouldAdd == False
. Also, since a
was in it, it now isn't and list1 == ['e']
. You can see where this is going.
Using your code, you can fix this by moving list1 = list(str)
to inside of your for word in str_list:
loop so that it reinitializes the list every time. I am going to try to find a more pythonic way of doing the function and post it when I can.
EDIT:
Here is my way of doing this:
>>> def is_sub_anagram(s, sub):
s = list(s)
try:
for c in sub: s.remove(c)
except:
return False
return True
>>> def find_sub_anagram_in_wordlist(s, str_list):
return list(filter(lambda x: is_sub_anagram(s,x), str_list))
>>> find_sub_anagram_in_wordlist('apple',['app','ppl','ae','le'])
['app', 'ppl', 'ae', 'le']
>>> find_sub_anagram_in_wordlist('apple',['app','ppl','ae','le','lle'])
['app', 'ppl', 'ae', 'le']
Upvotes: 1
Reputation: 15369
I think it will help to simplify what you're doing. In particular, separate the test for subanagramness functionally from the procedure for filtering the candidates. This would be my approach:
def is_sub_anagram( word, candidate ):
word = list( word )
for letter in candidate:
try:
word.remove( letter )
except ValueError:
return False
return True
def filter_sub_anagrams( word, candidates ):
return [ x for x in candidates if is_sub_anagram( word, x ) ]
print( filter_sub_anagrams( 'apple', [ 'ppl', 'al', 'app', 'apple', 'aapl' ] ) )
The output is:
['ppl', 'al', 'app', 'apple']
Note that 'aapl'
is not and should not be included in the output.
Upvotes: 1