0

I have written a simple for loop meant to check if all of the words in one list are found in a larger list. It is a practice question found here.

I do not understand why my function does not execute properly - After running it, what is left in the sample list "note2" is ['one','today'], so it seems like the loop is somehow skipping over those words. Why is that?! I do not understand it conceptually.

Thank you for your help on this.

Example lists (two pairs of examples):

mag1=['two', 'times', 'three', 'is', 'not', 'four']
note1=['two', 'times', 'two', 'is', 'four']

mag2=['give', 'me', 'one', 'grand', 'today', 'night']
note2=['give','one','grand','today']

Function:

def checkMagazine(magazine, note):
    #Counter(note1).max
    for word in note:
        if word in magazine:
            magazine.remove(word)
            note.remove(word)
            #print(magazine)
            #print(note)
        #print(note)
    if len(note)>0:
        #ans="No"
        print("No")
    else:
        #ans="Yes"
        print("Yes")
Z_D
  • 797
  • 2
  • 12
  • 30
  • I don't know for *absolute sure* that that's your problem, but it definitely sounds like it is. You can't reliably change the size of a collection (like removing from it) while iterating it. That can cause weird behavior (like elements getting skipped). Change to a list comprehension, or, have a second list that's a copy of the original. – Carcigenicate Nov 16 '19 at 17:17
  • Actually, arguably [this](https://stackoverflow.com/questions/742371/why-does-python-skip-elements-when-i-modify-a-list-while-iterating-over-it) is a better dupe. – Carcigenicate Nov 16 '19 at 17:18
  • If you do not want to iterate you can use something like this:`final = [word for word in mag1 if word not in note1]` – LocoGris Nov 16 '19 at 17:30

2 Answers2

2

In the loop you remove elements from the list and then word is looking at the elements of the reduced list.

Copy the lists in the for loop line using note[:]:

def checkMagazine(magazine, note):
    for word in note[:]:
        if word in magazine:
            magazine.remove(word)
            note.remove(word)

mag2=['give', 'me', 'one', 'grand', 'today', 'night']
note2=['give','one','grand','today']

checkMagazine(mag2, note2)

seralouk
  • 30,938
  • 9
  • 118
  • 133
1

As explained in this answer https://stackoverflow.com/a/58718886/313935 removing items from a list inside a loop is always a no-go. You can find out yourself by inspecting the result of the print statements you've commented out in your code (i.e. the position of items in the list changes every time an item is removed).

Here's another approach:

def checkMagazine(magazine, note):    
    matches=0
    for word in note:
        if word in magazine:
            matches+=1

    if matches==len(note):
        print("Yes")
    else:
        print("No")
dpant
  • 1,622
  • 19
  • 30