Reputation: 11
I have a to do list in the form of tuples...
[(datetime.datetime(2014, 2, 28, 0, 0), 'tutorial signons'), (datetime.datetime(2014, 4, 9, 0, 0), 'assignment 1'), (datetime.datetime(2014, 4, 22, 0, 0), 'assignment 2'), (datetime.datetime(2014, 6, 14, 0, 0), 'exam study'), (datetime.datetime(2014, 3, 15, 0, 0), 'buy groceries'), (datetime.datetime(2014, 3, 20, 0, 0), 'laundry'), (datetime.datetime(2014, 3, 26, 0, 0), 'maths assignment'), (datetime.datetime(2014, 3, 31, 0, 0), 'write todo list'), (datetime.datetime(2014, 4, 4, 0, 0), 'apply for a job'), (datetime.datetime(2014, 4, 14, 0, 0), 'procrastinate'), (datetime.datetime(2014, 4, 19, 0, 0), 'buy easter eggs'), (datetime.datetime(2014, 4, 25, 0, 0), 'buy anzac biscuits')]
and I'm trying to write a function that will remove a tuple from the list if the to do task matches a name, if no name is found it will return False. This is what I have so far, but I always get false, even if the task exists.
def remove_item(todolist, name):
for t in todolist:
if t[1] is name:
del t
else:
return False
Upvotes: 1
Views: 1888
Reputation: 379
The problem with your code is that you are testing for reference equality ('is'
operator) instead of value equality ('=='
operator).
E.g.
>>> a = 'tutorial signons'
>>> b = 'tutorial signons'
a is b
will return False
, but a == b
will return True
.
See this for more details.
Hence, this should do what you were expecting:
def remove_item(todo_list, name):
for t in todolist:
if t[1] == name:
del t
else:
return False
However, deleting elements from a list you are iterating is not a very good idea. You might want to create a new list or use something like:
filtered_list = filter(lambda x: x[1] != 'some_string', todo_list)
This will remove each tuple from the list that matches some_sting
.
Upvotes: 2
Reputation: 3661
There are a few things wrong with your code:
is
operator which compares object identity. Use ==
to get what you expect.filter
the list or use a list comprehension to get a new list.return False
statement is at the wrong indentation. It should be outside the for
loop.I would write the code like this:
def remove_item(todo_list, item):
return filter(lambda x: x[1] != item, todo_list)
Upvotes: 0
Reputation: 56674
Deleting an item from a list while iterating through it is a bad idea (it messes up the list iterator, so you skip the test item following every item you delete). If you have two items to be removed one after the other, well, you just failed.
There are three ways to get around this;
Iterate through the list in reverse order (a bit messy, but it works)
Use a list comprehension - build a new list, omitting the values to be "removed". This is usually the cleanest to read.
Iterate through the list and keep a list of indices to remove, then go through the list of indices to remove and delete (item i - number of items already removed), ie compensate for list shrinkage. Also messy.
Option 2 would look something like
def remove_item(todolist, name):
result = [item for item in todolist if name != item[1]]
if len(todolist) == len(result):
return False # nothing removed
else:
return result
Upvotes: 1