Skip to main content

Adding data structure

To add a mark as done feature, we will need a data structure to store the todos. Up until now, we only store todo as a string. With data structure, we can store more information about the todo, such as whether it is done or not.

Create the structure

A basic data structure is to imagine a table with 2 columns todo and done:

todois_done
Buy milkFalse
Wash shoesFalse
Print assignFalse

Then, how do we represent this table in Python? We can use a list of dictionaries:

todos = [
{
"todo": "Buy milk",
"is_done": False
},
{
"todo": "Wash shoes",
"is_done": False
},
{
"todo": "Print assignment",
"is_done": False
}
]

A dictionary is a data structure that stores key-value pairs. In this case, the keys are todo and is_done.The todo key stores the todo string, and the is_done key stores a boolean value, true means the todo is done, false means the todo is not done.

Implement the data structure

Let's update the add_todo function to use the new data structure. Instead of stroing the todo as a string, we will store it as a dictionary. And give a default value of False to is_done key.

# main.py

def main():
todos = []

todos = add_todo(todos, "Buy milk")
todos = add_todo(todos, "Wash shoes")
todos = add_todo(todos, "Print assignment")
print_todos(todos)

print("Removing todo at index 1")
todos = remove_todo(todos, 1)

print("----")
print_todos(todos)

def add_todo(todos: list, todo: str):
todos.append({
"todo": todo,
"is_done": False
})
return todos

def print_todos(todos: list):
for todo in todos:
print(f"- {todo}")

def remove_todo(todos: list, index: int):
todos.pop(index)
return todos

# this will run the `main` function when we run the program `python3 main.py`
if __name__ == "__main__":
main()

If you print the above code we will get the following output:

- {'todo': 'Buy milk', 'is_done': False}
- {'todo': 'Wash shoes', 'is_done': False}
- {'todo': 'Print assignment', 'is_done': False}
Removing todo at index 1
----
- {'todo': 'Buy milk', 'is_done': False}
- {'todo': 'Print assignment', 'is_done': False}

It will print the dictionary, we want to update the print_todos function to format the output instead of the dictionary

# main.py

def main():
todos = []

todos = add_todo(todos, "Buy milk")
todos = add_todo(todos, "Wash shoes")
todos = add_todo(todos, "Print assignment")
print_todos(todos)

print("Removing todo at index 1")
todos = remove_todo(todos, 1)

print("----")
print_todos(todos)

def add_todo(todos: list, todo: str):
todos.append({
"todo": todo,
"is_done": False
})
return todos

def print_todos(todos: list):
for todo in todos:
print(f"- {todo['todo']}")

def remove_todo(todos: list, index: int):
todos.pop(index)
return todos

# this will run the `main` function when we run the program `python3 main.py`
if __name__ == "__main__":
main()

In above code, we are using todo['todo'] to get the value of todo key in the dictionary. the ['todo']

Marking todo as done

Now, let's add a function mark_todo_done to mark a todo as done. What we will do is change the value of is_done key to True. We will use the index again to find the todo we want to mark as done.

# main.py

def main():
todos = []

todos = add_todo(todos, "Buy milk")
todos = add_todo(todos, "Wash shoes")
todos = add_todo(todos, "Print assignment")
print_todos(todos)

print("Removing todo at index 1")
todos = remove_todo(todos, 1)

print("----")
print_todos(todos)

print("Marking todo at index 0 as done")
todos = mark_todo_done(todos, 0)

print("----")
print_todos(todos)

def add_todo(todos: list, todo: str):
todos.append({
"todo": todo,
"is_done": False
})
return todos

def print_todos(todos: list):
for todo in todos:
print(f"- {todo['todo']}")

def remove_todo(todos: list, index: int):
todos.pop(index)
return todos

def mark_todo_done(todos: list, index: int):
todos[index]["is_done"] = True
return todos

# this will run the `main` function when we run the program `python3 main.py`
if __name__ == "__main__":
main()

If you run the above code, you will get the following output, there is no change in the output. We also need to update the print_todos function to show the is_done value.

# main.py

def main():
todos = []

todos = add_todo(todos, "Buy milk")
todos = add_todo(todos, "Wash shoes")
todos = add_todo(todos, "Print assignment")
print_todos(todos)

print("Removing todo at index 1")
todos = remove_todo(todos, 1)

print("----")
print_todos(todos)

print("Marking todo at index 0 as done")
todos = mark_todo_done(todos, 0)

print("----")
print_todos(todos)

def add_todo(todos: list, todo: str):
todos.append({
"todo": todo,
"is_done": False
})
return todos

def print_todos(todos: list):
for todo in todos:
if todo["is_done"]:
print(f"- [x] {todo['todo']}")
else:
print(f"- [ ] {todo['todo']}")

def remove_todo(todos: list, index: int):
todos.pop(index)
return todos

def mark_todo_done(todos: list, index: int):
todos[index]["is_done"] = True
return todos

# this will run the `main` function when we run the program `python3 main.py`
if __name__ == "__main__":
main()

In the above code, we are using if statement to check if the is_done value is True or False and print different output based on the is_done value.

If you run the above code, you will get the following output:

- [ ] Buy milk
- [ ] Wash shoes
- [ ] Print assignment
Removing todo at index 1
----
- [ ] Buy milk
- [ ] Print assignment
Marking todo at index 0 as done
---
- [x] Buy milk
- [ ] Print assignment