Reputation: 15
I'm creating a simple, personal library project with python. I have code that when somebody borrows a book, it will place the book into a json file with their id/library card number like this:
customers.json
{
"customers": [
{
"id": "1234",
"book": "Ulysses",
"book2": "War and Peace",
"book3": "Memoirs of Hadrian",
"book5": "Season of Migration to the North"
},
{
"id": "4321",
"book": "Mrs Dalloway",
"book2": "Great Expectations"
},
{
"id": "1973",
"book": "The Aeneid"
}
]
}
This code takes the user's input and loops through each of the values to find the corresponding key.
return_book_input = input('What book do you want to return: ')
with open ('customers.json') as f:
customer_data = json.load(f)
values = []
keys = []
def get_key():
for customer in customer_data['customers']:
for key, value in customer.items():
if return_book_input == value:
keys.append(key)
values.append(value)
print(keys, values)
write_json(customer_data, 'customers.json')
get_key()
Sample output:
['book2'] ['War and Peace']
Question: How do I delete this key value pair from the customer with the id: 1234
? I want to delete the key value pair with the key: 'book2'
and value: 'War and Peace'
. Also, is there a way to delete a dictionary key value pair based on value instead of key?
My goal isn't to get the fastest code but the easiest to write and read.
Upvotes: 1
Views: 66
Reputation: 25500
You already made a list containing the keys you want to delete. Now, move its declaration to inside the for customer in customer_data
loop, because you want to delete a fresh set of keys for every customer.
with open ('customers.json') as f:
customer_data = json.load(f)
return_book_input = "Ulysses"
for customer in customer_data['customers']:
keys_to_delete = []
for key, value in customer.items():
if return_book_input == value:
keys_to_delete.append(key)
for key in keys_to_delete:
del customer[key]
print(customer_data)
Now, the customer_data
dictionary doesn't contain the book1
key for the first customer.
{
"customers": [
{
"id": "1234",
"book2": "War and Peace",
"book3": "Memoirs of Hadrian",
"book5": "Season of Migration to the North"
},
{
"id": "4321",
"book": "Mrs Dalloway",
"book2": "Great Expectations"
},
{
"id": "1973",
"book": "The Aeneid"
}
]
}
This doesn't seem like a great way to structure your data, though. If you have the ability to change it, I strongly suggest you do. Each customer dictionary will have a key "id"
for their customer id, and a key "books"
for the books they borrowed. The value of the books
key will be a list. This way, your object structure doesn't change when a customer borrows multiple books -- you simply add more entries to the list.
customers.json:
{
"customers": [
{
"id": "1234",
"books": ["Ulysses", "War and Peace", "Memoirs of Hadrian", "Season of Migration to the North"]
},
{
"id": "4321",
"books": ["Mrs Dalloway", "Great Expectations"]
},
{
"id": "1973",
"books": ["The Aeneid"]
}
]
}
Then, you'd use list.remove()
to remove the book -- no explicit iterating required, list.remove()
handles it for you. If the book doesn't exist in the list, a ValueError
is thrown that we can catch to detect when this happens:
with open ('customers.json') as f:
customer_data = json.load(f)
for customer in customer_data["customers"]:
try:
customer["books"].remove(return_book_input)
print(f"Thank you for returning {return_book_input}, Customer {customer['id']}")
except ValueError:
print(f"Customer {customer['id']} hasn't borrowed the book {return_book_input}")
This gives the output:
Thank you for returning Ulysses, Customer 1234
Customer 4321 hasn't borrowed the book Ulysses
Customer 1973 hasn't borrowed the book Ulysses
And once we're done, customer_data
is:
{
"customers": [
{
"id": "1234",
"books": [ "War and Peace", "Memoirs of Hadrian", "Season of Migration to the North" ]
},
{
"id": "4321",
"books": [ "Mrs Dalloway", "Great Expectations" ]
},
{
"id": "1973",
"books": [ "The Aeneid" ]
}
]
}
In fact, you don't even need to iterate over the customers! Since you probably know your customer's ID already (it's presumably on their library card), customer_data["customers"]
could be a dict. The keys of this dict are the customer ID. The values are the dictionaries for each customer, same as before.
customer.json:
{
"customers": {
"1234": {
"id": "1234",
"books": [ "War and Peace", "Memoirs of Hadrian", "Season of Migration to the North" ]
},
"4321": {
"id": "4321",
"books": [ "Mrs Dalloway", "Great Expectations" ]
},
"1973": {
"id": "1973",
"books": [ "The Aeneid" ]
}
}
}
Then, after reading the json you'd simply do:
customer_id = "1234" # input("Enter Customer ID: ")
return_book_input = "Ulysses" # input("Enter book: ")
try:
# Find the correct customer
customer = customer_data["customers"][customer_id] # If fail throws KeyError
# Remove book
customer["books"].remove(return_book_input) # If fail throws ValueError
print(f"Thank you for returning {return_book_input}, Customer {customer['id']}")
except KeyError: # Handle no customer
print(f"Customer {customer_id} does not exist")
except ValueError: # Handle no book
print(f"Customer {customer['id']} hasn't borrowed the book {return_book_input}")
Upvotes: 2