Removing a key from a dictionary using the value - python

Can I somehow delete a value from a dictionary using its key?
The function del_contact is supposed to delete a contact using only the name of the contact, but unfortunately I have the dictionary and the value, but not the key. How can this be solved?
my_contacts = {
1: {
"Name": "Tom Jones",
"Number": "911",
"Birthday": "22.10.1995",
"Address": "212 street"
},
2: {
"Name": "Bob Marley",
"Number": "0800838383",
"Birthday": "22.10.1991",
"Address": "31 street"
}
}
def add_contact():
user_input = int(input("please enter how many contacts you wanna add: "))
index = len(my_contacts) + 1
for _ in range(user_input):
details = {}
name = input("Enter the name: ")
number = input("Enter the number: ")
birthday = input("Enter the birthday")
address = input("Enter the address")
details["Name"] = name
details["Number"] = number
details["Birthday"] = birthday
details["Address"] = address
my_contacts[index] = details
index += 1
print(my_contacts)
def del_contact():
user_input = input("Please enter the name of the contact you want to delete: ")
my_contacts.pop(user_input)
add_contact()
print(my_contacts)
The problem is that my key of the dictionary is 1 or Name, and I want to be able to remove the contact using only the value of Name.

Basically what you can do is iterate of the dict and save only the keys without that user's name.
This code will do the trick:
my_contacts = {1: {"Name": "Tom Jones",
"Number": "911",
"Birthday": "22.10.1995",
"Address": "212 street"},
2: {"Name": "Bob Marley",
"Number": "0800838383",
"Birthday": "22.10.1991",
"Address": "31 street"}
}
user_input = "Tom Jones"
my_contacts = {key: value for key, value in my_contacts.items() if value["Name"] != user_input}

There's two steps here:
Finding the key/value pair(s) that match
Deleting the keys you found
If you're only deleting a single item (even with multiple matches), always, these can be combined:
def del_contact():
user_input = input("Please enter the name of the contact you want to delete: ")
for k, v in my_contacts.items(): # Need both key and value, we test key, delete by value
if v["Name"] == user_input:
del my_contacts[k]
break # Deleted one item, stop now (we'd RuntimeError if iteration continued)
else:
# Optionally raise exception or print error indicating name wasn't found
If you might delete multiple entries, and must operate in place, you'd split the steps (because it's illegal to continue iterating a dict while mutating the set of keys):
def del_contact():
user_input = input("Please enter the name of the contact you want to delete: ")
to_delete = [k for k, v in my_contacts.items() if v["Name"] == user_input]
if not to_delete:
# Optionally raise exception or print error indicating name wasn't found
for k in to_delete:
del my_contacts[k]
Or if you're okay with replacing the original dict, rather than mutating it in place, you can one-line the multi-deletion case as:
def del_contact():
global my_contacts # Assignment requires explicitly declared use of global
user_input = input("Please enter the name of the contact you want to delete: ")
my_contacts = {k: v for k, v in my_contacts.items() if v["Name"] != user_input} # Flip test, build new dict
# Detecting no matches is more annoying here (it's basically comparing
# length before and after), so I'm omitting it

I think thats what you need, hope that helps:
Code:
my_contacts = {1: {"Name": "Tom Jones",
"Number": "911",
"Birthday": "22.10.1995",
"Address": "212 street"},
2: {"Name": "Bob Marley",
"Number": "0800838383",
"Birthday": "22.10.1991",
"Address": "31 street"}
}
def add_contact():
user_input = int(input("please enter how many contacts you wanna add: "))
index = len(my_contacts) + 1
for _ in range(user_input):
details = {}
name = input("Enter the name: ")
number = input("Enter the number: ")
birthday = input("Enter the birthday")
address = input("Enter the address")
details["Name"] = name
details["Number"] = number
details["Birthday"] = birthday
details["Address"] = address
my_contacts[index] = details
index += 1
print(my_contacts)
add_contact()
print(my_contacts)
def del_contact():
user_input = input("Please enter the name of the contact you want to delete: ")
values = [key for key in my_contacts.keys() if user_input in my_contacts[key].values()]
for value in values:
my_contacts.pop(value)
del_contact()
print(my_contacts)
Input:
{1: {'Name': 'Tom Jones', 'Number': '911', 'Birthday': '22.10.1995', 'Address': '212 street'}, 2: {'Name': 'Bob Marley', 'Number': '0800838383', 'Birthday': '22.10.1991', 'Address': '31 street'}, 3: {'Name': 'myname', 'Number': '1233455', 'Birthday': '12-12-22', 'Address': 'blabla street'}}
Please enter the name of the contact you want to delete: Bob Marley
Output:
{1: {'Name': 'Tom Jones', 'Number': '911', 'Birthday': '22.10.1995', 'Address': '212 street'}, 3: {'Name': 'myname', 'Number': '1233455', 'Birthday': '12-12-22', 'Address': 'blabla street'}}

Being that the index are used as keys for the dictionary, the range function can be used as follows:
def del_contact():
user_input = input("Please enter the name of the contact you want to delete: ")
for i in range(1,len(my_contacts)+1):
if my_contacts[i]['Name'] == user_input:
del my_contacts[i]
break
If there can be multiple contacts with the same name that need to be deleted, remove the break statement.
But as mentioned in the comments, there is no need to use an index as a key for the dictionaries. A potential bug you'll encounter with that, is if the first entry is deleted whose name is Tom Jones the dict will have a length of 1 with only one key - 2. Then when you try to add more contacts, when you check the length of the dictionary index = len(my_contacts) + 1, since length is 1, index will be 2. Hence my_contacts[index] = details will update the contact with a key of 2 or "Name": "Bob Marley" instead of adding a new contact.

Related

Return value from nested dictionary in Python

I'm trying to get values from a nested dict via user input. The problem is that the nested dictionaries have generic names (d1,d1, etc.). The user inputs, say, last name and the program returns the email.
I know this is basic, so I apologize in advance. This is what I have so far.
my_dict = {
'd1':{
'fname':'john',
'lname':'doe',
'age':'26',
'email':'jdoe#mail.com'
},
'd2':{
'fname':'mary',
'lname':'jane',
'age':'32',
'email':'mjane#mail.com'
}
}
lname = input("enter last name: ")
for emp in my_dict.items():
print(emp)
Output:
enter last name: john
('d1', {'fname': 'john', 'lname': 'doe', 'age': '26', 'email': 'jdoe#mail.com'})
('d2', {'fname': 'mary', 'lname': 'jane', 'age': '32', 'email': 'mjane#mail.com'})
This is a function that takes a last name as input, then iterates over each dictionary (key, value) pair and returns the email as soon as there is a match:
def get_email_from_last_name(last_name):
for v in my_dict.values():
if v['lname'] == last_name:
return v['email']
lname = input("enter last name: ")
email = get_email_from_last_name(lname)
print(email)
prints:
enter last name: doe
jdoe#mail.com
Per OP's comment, here is a solution with a simple tuple instead:
my_data = (
{
'fname':'john',
'lname':'doe',
'age':'26',
'email':'jdoe#mail.com'
},
{
'fname':'mary',
'lname':'jane',
'age':'32',
'email':'mjane#mail.com'
}
)
lname = input("enter last name: ")
for person in my_data:
if lname == person["lname"]:
print(person)
You can also map according to the last name, but that is not necessarily a one-to-one relationship.

How to show more variables in modules

Im just starting to learn practice it however my problem I bet is easy to resolve I’m trying my best but my knowledge is too low to solve this out , I’ve try commas brackets but still didn’t work I just want to get print the name country and age , sorry for newbie question please help 👍🏼💪🤠
Main.py
import one
a = one.person1["name"]
b = one.person2["name"]
c = one.person3["name"]
def input():
print(one(name))
One.py
person1 = {
"name": "John",
"age": "6",
"country": "Norway"
}
person2 = {
"name": "Jn",
"age": "36",
"country": "Norway"
}
person3 = {
"name": "krun",
"age": "36",
"country": "Norway"
}
If you want to display one person then use every key separatelly
print( one.person1["name"], one.person1["age"], one.person1["country"] )
And then you can format output
print('name =', one.person1["name"])
print('age =', one.person1["age"])
print('country =', one.person1["country"])
You can also display directly print(one.person1) but then you can't format output.
If you want to display all persons then keep them on list and then you can use for-loop
persons = [one.person1, one.person2, one.person2]
for item in persons:
print( item["name"], item["age"], item["country"] )
If you don't know keys then you can use .keys() or .items() in dictionary
for item in persons:
for key, value in item.items():
print(key, '=', value)
if you want to get key from user then
key = input("what to show: ")
print(one.person1[key])
print(one.person2[key])
print(one.person3[key])
or better keep persons on list and use for-loop
key = input("what to show: ")
persons = [one.person1, one.person2, one.person2]
for item in persons:
print( item[key] )

How to update user input result in while loop?

I'm trying to give the user information about the product, but how can I give it to them in case they add another product to the order?
import datetime
db = [
{
'product': 'cola',
'price': {
'USD': '2',
'GEL': '6'
},
'amount': 20,
'validity': '17/12/2019'
},
{
'product': 'cake',
'price': {
'USD': '3',
'GEL': '9'
},
'amount': 15,
'validity': '17/12/2019'
},
{
'product': 'tea',
'price': {
'USD': '1',
'GEL': '3'
},
'amount': 14,
'validity': '17/12/2019'
},
]
amount_of_product = {}
validity_of_product = {}
prices_of_product = {}
for i in db:
amount_of_product.update({i["product"]: i["amount"]})
validity_of_product.update({i["product"]: i["validity"]})
prices_of_product.update({i["product"]: i["price"]})
adLoop = True
final_price = []
while adLoop:
user_input = input("Please enter a product name: ")
if user_input in amount_of_product.keys() and validity_of_product.keys():
print(f"Currently, we have {amount_of_product[user_input]} amount of {user_input} left, "
f"which are valid through {validity_of_product[user_input]}")
user_input_two = int(input("Please enter the amount: "))
user_input_three = input("In which currency would you like to pay in?(GEL or USD: ").upper()
price = prices_of_product[user_input][user_input_three]
total = user_input_two * int(price)
if user_input_three == "GEL":
final_price.append(total)
print(f"Your order is: {user_input_two} {user_input} and total price for it is: {total}₾")
elif user_input_three == "USD":
final_price.append(total * 3)
print(f"Your order is: {user_input_two} {user_input} and total price for it is: {total}$")
stop_or_order = input("Would you like to add anything else?: ")
if stop_or_order == "yes":
adLoop = True
elif stop_or_order == "no":
adLoop = False
so if user orders cola and cake, I want the output to look like this:
Your order is 1 cola and 1 cake and total price of it is: sum(final_price)
But every time I execute the code, the older input gets removed and I get the newer input as a result. I want to save it somewhere and show the user everything he/she ordered.
You're defining user_input inside the loop, so it gets overwritten each iteration. You could define an dict
user_shopping_cart = {
'cola':0,
'cake':0,
'tea':0
}
before the while loop and update the cart as the user puts items inside,
then generate the output with data from the cart.

Verify the date of birth taken as user input with the value stored in nested dictionary in a list in python

I am trying to verify date of birth taken from user and comparing it with the value stored in dictionary database. But it is not verifying the value even if I have entered the right value of date of birth. Here is my code:
from collections import defaultdict
accountDetails = [
{"FirtsName": "JOHN", "LastName": "DENIS","date of Birth": "01-06-1992", "Account Number": "432524352345234", "Account Balance": "50000"},
{"FirtsName": "AKASH", "LastName": "MAHAJAN", "date of Birth": "04-02-1995","Account Number": "432524352345234", "Account Balance": "50000"},
{"FirtsName": "AMAN", "LastName": "RANA","date of Birth": "11-04-1996", "Account Number": "432524352345234", "Account Balance": "50000"},
{"FirtsName": "ANKUR", "LastName": "JAIN","date of Birth": "21-05-1990", "Account Number": "432524352345234", "Account Balance": "50000"},
]
d = defaultdict(lambda: defaultdict(dict))
for item in accountDetails:
d[item['FirtsName']][item['LastName']][item['date of Birth']] = item
# get valid first name
while True:
first_name_input = input('Enter First Name:\n').upper()
if first_name_input in d:
break
else:
print('Enter valid First Name')
# get valid last name
while True:
last_name_input = input('Enter Last Name:\n').upper()
if last_name_input in d[first_name_input]:
break
else:
print('Enter valid Last Name')
# get valid last name
while True:
dob_input = input('Enter dob:\n')
if dob_input in d[first_name_input]:
break
else:
print('Enter valid dob')
print(d[first_name_input][last_name_input])
The user has put the value as-04-02-1995
You need to test versus keys in the second level of your nested dictionary:
while True:
dob_input = input('Enter dob:\n')
if dob_input in d[first_name_input][last_name_input]:
break
else:
print('Enter valid dob')
This becomes clear when you print the structure of the nested dictionary you have created:
print(d)
defaultdict(<function __main__.<lambda>>,
{'AKASH': defaultdict(dict,
{'MAHAJAN': {'04-02-1995': {'Account Balance': '50000',
'Account Number': '432524352345234',
'FirtsName': 'AKASH',
'LastName': 'MAHAJAN',
'date of Birth': '04-02-1995'}}}),
...
'JOHN': defaultdict(dict,
{'DENIS': {'01-06-1992': {'Account Balance': '50000',
'Account Number': '432524352345234',
'FirtsName': 'JOHN',
'LastName': 'DENIS',
'date of Birth': '01-06-1992'}}})})

Print key-value pairs of a dictionary in python

How I can print key-value pairs in this situation:
a = [
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]
search_name = 'Tom'
for i in a:
for key in i:
if (i[key] == search_name):
print (item for item in a).next()
else:
print 'No Name'
I don't want to see 'No name' message
A cleaner way to achieve it would be:
for dic in a:
name = dic.get('name') # will return None if dic has no `name` key
if name and name == search_name:
print dic
else:
print 'No Name'
But anyway, if don't wan't to see No Name then simply don't print it.
Of course You see it. You iterate over dictionary keys (for key in i) and when You try to match i["age"] with search_name, it will show No Name.
try
for dict in a:
if search_name in dict.values():
print dict
else:
print "No name"

Categories