Search code examples
pythondata-sciencedata-analysis

'list' object has no attribute 'lower' in Python


function anagrams(s1, s2) is a Boolean valued function, which returns true just in case the string s1 contains the same letters as string s2 but in a different order. The function should be case insensitive --- in other words it should return the same value if any letters in either s1 or s2 are changed from upper to lower case or from lower to upper case. You may assume that the input strings contain only letters. enter image description here

The function find_all_anagrams(string) takes a string as input and returns a list of all words in the file english_words.txt that are anagrams of the input string. the function should return a list [word1, ..., wordN] such that each word in this list is a word in the dictionary file such that the value function anagrams(string, word) are True

def anagrams( string1, string2 ):
    str_1 = string1.lower()
    str_2 = string2.lower()
    if str_1 == str_2:
        return False
    else:
        list_1 = list( str_1 )
        list_1.sort()
        list_2 = list( str_2 )
        list_2.sort()
        return list_1 == list_2

def find_all_anagrams( string ):
    with open("english_words.txt") as f:
        word_list = []
        for line in f.readlines():
            word_list.append(line.strip())
        list1 = [i.split() for i in word_list]
    for j in list1:
        if anagrams( string, j ) == True:
            return list1
        else:
            return []

ERROR kept saying this: AttributeError: 'list' object has no attribute 'lower'

for example,word_list contains: ['pyruvates', 'python', 'pythoness', 'pythonesses', 'pythonic', 'pythons', 'pyuria', 'pyurias', 'pyx', 'pyxes']

Expected output below enter image description here Part of the txt file shown on the right: enter image description here

Update: I think I just solved it,here are my codes:

def find_all_anagrams( string ):
    list1 = []
    with open("english_words.txt") as f:
        word_list = []
        for line in f.readlines():
            word_list.append(line.strip())
    for i in word_list:
            if anagrams( string, i ):
                list1.append(i)
    return list1

Solution

  • You are using split() function at this part:

    list1 = [i.split() for i in word_list] 
    

    Let's see what the documentation tells us about that function:

    str.split(sep=None, maxsplit=-1)

    Return a list of the words in the string, using sep as the delimiter string. If maxsplit is given, at most maxsplit splits are done (thus, the list will have at most maxsplit+1 elements). If maxsplit is not specified or -1, then there is no limit on the number of splits (all possible splits are made).

    It returns a list, and you added that list to your own list. I can see that word_list is meant to hold lines of words. Let's assume that word_list looks like this:

    word_list = ["hello darkness my", "old friend I've", "come to see you", "again"]
    

    What happens after list1 = [i.split() for i in word_list]?

    list1 = [i.split() for i in word_list]
    print(list1)
    

    Output:

    [['hello', 'darkness', 'my'], ['old', 'friend', "I've"], ['come', 'to', 'see', 'you'], ['again']]
    

    As you can see, elements are individual lists. At this part of your code:

    for j in list1:
        if anagrams( string, j ) == True:
            return list1
        else:
            return []
    

    j is a list, therefore here:

    def anagrams( string1, string2 ):
        str_1 = string1.lower()
        str_2 = string2.lower()
    

    str_2 = string2.lower() is trying to call lower method on a list, which isn't a valid method for a list object, and that's why Python is complaining.

    List Comprehension might look "cool" but often using simple loops benefits your code's readability, and in some cases might even avoid mistakes like this one. Here is my alternative:

    list1 = []
    for i in word_list:
      for word in i.split():
        list1.append(word)
    

    see the output:

    print(list1)
    
    ['hello', 'darkness', 'my', 'old', 'friend', "I've", 'come', 'to', 'see', 'you', 'again']
    

    Single words as you intended.