+ 1

Python remove method error in ouput

#Write a function called attendance_check. attendance_check #should have two parameters: roster and present. Both roster #and present will be lists of strings. Return a list (sorted #alphabetically) of all strings in the list roster that are #not in the list present. In other words, if roster is a #list of students enrolled in a class and present is a list #of students in class today, return a list of students that #are absent. ************************************************************************************************ def attendance_check(roaster, present): for item in roaster: if item in present: roaster.remove(item) return roaster test_roster = ['Jessica', 'Nick', 'Winston', 'Schmidt', 'Cece', 'Ferguson'] test_present = ['Nick', 'Cece', 'Schmidt', 'Jessica'] print(attendance_check(test_roster, test_present)) ****************************************************************** my answer is ['Nick', 'Winston', 'Cece', 'Ferguson'] which is wrong But the answer should be: ******************************************************************* ['Ferguson', 'Winston'] ******************************************************************** I tried to debug this code and found out that every time I remove an item from the roaster, it is skipping the next item in the roaster and taking the item after that.. but I dont understand why.. Can anybody please explain why this is happening

25th Sep 2020, 4:17 PM
NG_
NG_ - avatar
3 Answers
+ 6
This task can also be solved by using a total different approach. When we use the 2 lists and convert them to a set, we can use the set.difference() method to get the result: def attendance_check(roster_, present_): return sorted(set(roster).difference(set(present))) roster = ['Jessica', 'Nick', 'Winston', 'Schmidt', 'Cece', 'Ferguson'] present = ['Nick', 'Cece', 'Schmidt', 'Jessica'] print(attendance_check(roster, present)) # >>> result will be: ['Ferguson', 'Winston'] -------------- using your code and doing a small change in for loop, does also give the correct result: def attendance_check(roster, present): for item in roster[:]: # <<< by using [:] a copy of roster is used to iterate and avoids the problem you have. if item in present: roster.remove(item) return roster test_roster = ['Jessica', 'Nick', 'Winston', 'Schmidt', 'Cece', 'Ferguson'] test_present = ['Nick', 'Cece', 'Schmidt', 'Jessica'] print(attendance_check(test_roster, test_present))
25th Sep 2020, 5:44 PM
Lothar
Lothar - avatar
+ 3
You should never mutate a list that you are looping over. It can lead to unwanted side effect, especially when you are removing elements inside the loop. Also it is usually better to keep the original data unchanged, and make a brand new list. You can use a loop like you did, just append the name to the result list, if it is eligible. Arguably a more elegant (and pythonic) solution would be to use a list comprehension instead. Don't forget to sort before you return the result.
25th Sep 2020, 4:45 PM
Tibor Santa
Tibor Santa - avatar
+ 2
thank you so much Tibor. My code works fine now..
25th Sep 2020, 5:04 PM
NG_
NG_ - avatar