Creating dictionaries inside dictionaries based on user input - python

New to programming, and teaching myself by making a to-do list app that stores things to do in a dictionary called ThingsToDo, based on user input. I'm using the dict.update function, which is working, but I want to add a feature so that in the dictionary ThingsToDo, every time a user inputs a new thing to do, it stores the new item as a dictionary inside ThingsToDo, with things like Due Date, and Status inside that sub-dictionary. How can I do this?
Here is the code so far (just started):
ThingsToDo = {}
while True:
item = input("What do you need to do? ")
DueDate = input("When do you need to do it by? ")
status = "Not done."
ThingsToDo.update({
"Item": item,
"Due Date": DueDate,
"Status": status,
})
print(ThingsToDo)

First I suggest you to think about what will be the key(s) of your dictionary(ies). I can suggest you this simple solution using "what you need to do" as a key. It works well:
ThingsToDo = {}
while True:
item = input("What do you need to do? ")
DueDate = input("When do you need to do it by? ")
status = "Not done."
ThingsToDo.update({item: {"Due Date": DueDate, "Status": status}})
print(ThingsToDo)
Output example:
What do you need to do? Wash the car
When do you need to do it by? 2018/09/01
{'Wash the car': {'Due Date': '2018/09/01', 'Status': 'Not done.'}}
What do you need to do? Sort papers
When do you need to do it by? 2018/08/23
{'Wash the car': {'Due Date': '2018/09/01', 'Status': 'Not done.'},
'Sort papers': {'Due Date': '2018/08/23', 'Status': 'Not done.'}}

You have "many" things to do, so you can put that dict in a list, or a dict.
You cannot put that in a set beacuse it has to be hashable.
If you chose a dict, you have to chose a "key" for each element, right?
You can read about "data structures" here .
Let's try list :
thingsToDo = []
newThingToDo = {
'Item': 'I need a haircut',
'DueDate': 'Right now',
'Status': 'Done'
}
thingsToDo.append(newThingToDo)
Using a dict would allow you to order your tasks, but I'm not sure it is your question. Let's try ordering your tasks by adding a number.
thingsToDo = {}
newThingToDo = {
'Item': 'I need a haircut',
'DueDate': 'Right now',
'Status': 'Done'
}
thingsToDo[5] = newThingToDo
So your haircut is task number 5.
If you choose the dict way, your code could look like this :
# -*- coding: utf-8 -*-
thingsToDo = {}
while True:
n = int(input("How many tasks do you want to add?"))
for i in range(n):
item = input("What do you need to do? ")
duedate = input("When do you need to do it by? ")
status = "Not done."
newThingToDo = {
'Item': item,
'DueDate': duedate,
'Status': status
}
thingsToDo[i] = newThingToDo
print(thingsToDo)

Related

How to modify a dict item in a list

I have a list made of dictionaries
bookLogger = [
{'BookName': 'Noise', 'Author': 'Daniel Kahneman', 'Process': 'Reading' },
{'BookName': 'Superintelligence', 'Author': 'Nick Bostrom', 'Process': 'Not Reading'}
]
Want a user to be able to input what they want to change the name to, so that 'BookName': 'Noise' turns to 'BookName': 'Testing'
What I've come up with
testing = input("Enter Book Name ")
def changeName(bookLogger, testing, Name):
for options in bookLogger:
if options['BookName'] == testing:
options['BookName'] = Name
changeName(bookLogger, "BookName", "Chicken")
EDIT: Got it to work by doing
Updated = input("Enter Book Name ")
def changeName(Name):
for options in bookLogger:
if options['BookName'] == Updated:
options['BookName'] = Name
print(bookLogger)
You have many options. If you intend to modify the dict without returning a new dict, you can modify like this:
def rename(books: list[dict], old: str, new: str) -> None:
for book in books:
if book["name"] == old:
book["name"] = new
if __name__ == "__main__":
books = [{"name": "BookName"}, {"name": "A Book"}]
print(books)
rename(books, "BookName", "Chicken")
print(books)
Which yields:
[{'name': 'BookName'}, {'name': 'A Book'}]
[{'name': 'Chicken'}, {'name': 'A Book'}]
note: Type hints are used here but not required. I was simply specifying, for clarity in this case, that the inputs needed to be a list of dicts and two strings. In addition, these features can be enabled in some older versions of python using future.
from __future__ import annotations

Divide list into two parts based on condition python

I have a list which contains a chat conversation between agent and customer.
chat = ['agent',
'Hi',
'how may I help you?',
'customer',
'I am facing issue with internet',
'agent',
'Can i know your name and mobile no.?'
'customer',
'john doe',
'111111',..... ]
This is a sample of chat list.
I am looking to divide the list into two parts, agent_chat and customer_chat, where agent_chat contains all the lines that agent said, and customer_chat containing the lines said by customer.
Something like this(final output).
agent_chat = ['Hi','how may I help you?','Can i know your name and mobile no.?'...]
customer_chat = ['I am facing issue with internet','john doe','111111',...]
I'm facing issues while solving this, i tried using list.index() method to split the chat list based on indexes, but I'm getting multiple values for the same index.
For example, the following snippet:
[chat.index(l) for l in chat if l=='agent']
Displays [0, 0], since its only giving me first occurrence.
Is there a better way to achieve the desired output?
index() returns only the first index of the element so you'll need to accumulate the index of all occurrence by iterating over the list.
I would suggest to solve this using a simple for loop as:
agent_chat = []
customer_chat = []
chat_type = 'agent'
for chat in chats:
if chat in ['agent', 'customer']:
chat_type = chat
continue
if chat_type == 'agent':
agent_chat.append(chat)
else:
customer_chat.append(chat)
Other approaches like list comprehension will require two iterations of the list.
This would be my solution to your problem.
chat = ['agent',
'Hi',
'how may I help you?',
'customer',
'I am facing issue with internet',
'agent',
'Can i know your name and mobile no.?',
'customer',
'john doe',
'111111']
agent_list = []
customer_list = []
agent = False
customer = False
for message in chat:
if message == 'agent':
agent = True
customer = False
elif message == 'customer':
agent = False
customer = True
elif agent:
agent_list.append(message)
elif customer:
customer_list.append(message)
else:
pass
Here is my solution. I don't know this is the best one but I hope it helps
def chat_lists(chat):
agent_chat = []
customer_chat = []
user_flag = ""
for message in chat:
if message == 'agent':
user_flag = 'agent'
elif message == 'customer':
user_flag = 'customer'
else :
if user_flag == 'agent':
agent_chat.append(message)
else:
customer_chat.append(message)
return customer_chat, agent_chat
You can do something like this.
chat = ['agent',
'Hi',
'how may I help you?',
'customer',
'I am facing issue with internet',
'agent',
'Can i know your name and mobile no.?'
'customer',
'john doe',
'111111']
agent = []
customer = []
for j in chat:
if j=='agent':
curr = 'agent'
continue
if j=='customer':
curr = 'customer'
continue
if(curr=='agent'):
agent.append(j)
else:
customer.append(j)
print(agent)
print(customer)
You can set up a while loop to parse through the messages, and set up a variable to act as a 'switch' for whether the agent or client is talking.
# Get the current speaker (first speaker)
current_speaker = chat[0]
# Make the chat logs
agent_chat = []
customer_chat = []
# Iterate for the array
for message in chat:
# If the current speaker is updated
if message in ['agent', 'customer']:
# Then update the speaker
current_speaker = message
# Skip to the next iteration
continue
# Add the message based
if current_speaker == 'agent':
agent_chat.append(message)
else:
customer_chat.append(message)
Another note to keep in mind is that this whole system will bug out heavily if a customer or agent decides, for whatever reason, to type in the word 'agent' or 'customer'.

Editing Dictionary via User Input - Python

I am creating a program which requires the user to make changes to the dictionary. I can do these with a normal dictionary, however I was advised to hold my data in 'sub dictionaries' like the one below.
I've tried to see if I can get it working by having it change the values for all of the fields in each entry, but even that doesn't seem to be working. I am quite new to python so please bear with me!
VDatabase = {
"1200033944833": {
'MAP' : 'XXXX',
'CODE' : '0123',
'Method': 'R',
'Code1': 'S093733736',
'Reg ID' : '01'
}
Search = input("Search ACCOUNT:")
tmp_dict = VDatabase.get(Search, None)
print(tmp_dict if tmp_dict else "No ACCOUNT Found. \"{}\"".format(Search))
VDatabase["CODE"] = input("Enter CODE:")
print("Changing CODE...")
I was looking to change the value of CODE to whatever the user Input is.
Unfortunately it doesn't do anything, I can alter a regular Dictionary, so I think it's due to it being a 'sub-dictionary' so how would I access these values?
Here in the line,
VDatabase["CODE"] = input("Enter CODE:")
You are trying to change the value of 'CODE' directly in VDatabase but not inside the sub-dictionary that you have searched for.
Search = str(input("Search ACCOUNT:"))
tmp_dict = VDatabase.get(Search, None)
print(tmp_dict if tmp_dict else "No ACCOUNT Found. \"{}\"".format(Search))
VDatabase[Search]["CODE"] = str(input("Enter CODE:"))
print(VDatabase[Search])
or
tmp_dict['CODE'] = str(input("Enter CODE:"))
You will see that the main dictionary has changed.
I have changed the input type to str so that the value won't be integer while searching.

Return different value when querying dictionary

I am pulling from a dictionary in Python. I have it setup like this:
entries = [
{'website': 'yahoo','username': 'jblumberg','password': 'sdkljfhwe'},
{'website': 'google','username': 'jblumberg1','password': 'CoIushujSetu'}
]
I am asking the user to give me a website so I can return the password as so:
def lookup_password(website):
if website in entries.keys():
encrypted_password = entries[website]
return password_encrypt(encrypted_password, -encryption_key)
pass
However that won't give me what I want. How do I set it up to give me the password value for the provided website?
First let's restructure your dict like this so that it's a dict with each key as a website, like it seems you treat it in your code:
entries = {
'yahoo': {'username': 'jblumberg', 'password': 'sdkljfhwe'},
'google': {'username': 'jblumberg1', 'passwprd': 'CoIushujSetu'}
}
Now a couple of changes to your original code gets us to what should be working:
if website in entries:
encrypted_password = entries[website]['password']
I should note that website in entries and website in entries.keys() do the same thing here.
There are multiples small problems in your conception of your data :
First entries is a list. Therefore you won't be able to call ".keys()"
Also when using
encrypted_password = entries[website]
this will store the whole dictionnary. Meaning that you would then be able to access the password via ['password']
encrypted_password = entries[website]['password']
To resume : if you change you data to look like this
entries = {
'yahoo':{
'username': 'jblumberg','password': 'sdkljfhwe'
},
'google':{
'username': 'jblumberg1','password': 'CoIushujSetu'
},
}
def lookup_password(website):
if website in entries:
encrypted_password = entries[website]['password']
return password_encrypt(encrypted_password, -encryption_key)
pass
But if you keep the same data, it will have to look like this:
def lookup_password(website):
for record in entries:
if record['website'] == website:
encrypted_password = record['website']
return password_encrypt(encrypted_password, -encryption_key)
pass
You could use another dictionary:
entries = [
{'yahoo':{'username': 'jblumberg','password': 'sdkljfhwe'},
{'google':{'username': 'jblumberg1','password': 'CoIushujSetu'}
]
Then the following would happen:
>> website = 'yahoo'
>> entries[website]
>> {'username': 'jblumberg','password': 'sdkljfhwe'}
so if you wanted the password:
>> entires[website]['password']
>> 'sdkljfhwe'
Try:
def lookup_password(website):
for entry in entries:
if entry['website'] == website:
return entry['password']
Output:
In[2]: lookup_password('google')
Out[2]: 'CoIushujSetu'

Copying a dictionary into another dictionary

I'm working on a game and one of the commands, one to pickup items, is not working. The code pretty much checks to see if the item is in the room and if it is then to copy that to the players inventory and then delete the item from the room. However no matter what I try it either does nothing or copies the keys inside to the dictionary.
Here's the code:
def pickup(self, item):
conf = input('Do you want to pick up the ' + item.lower() + ': ')
if conf.lower() == 'y' or 'yes':
try:
self.inventory.update(room[self.room_number]['items'][item])
del room[self.room_number]['items'][item]
except KeyError:
print('You look everywhere but can\'t find a ' + item.lower())
else:
print('You consider it, but decide not to pick up the ' + item.lower())
When I print the inventory dictionary I get this
player.inventory
{
'type': 'weapon',
'equippable': True,
'value': 0,
'desc': 'a wooden stick, could be useful',
'name': 'Wooden Stick',
'perks': {
'defense': 0,
'health': 0,
'damage': 6,
'magic_damage': 0
}
}
or
{}
What I want is this:
player.inventory
{
'wooden stick':{
'type': 'weapon',
'equippable': True,
'value': 0,
'desc': 'a wooden stick, could be useful',
'name': 'Wooden Stick',
'perks': {
'defense': 0,
'health': 0,
'damage': 6,
'magic_damage': 0
}
}
Does anybody know how I can get this result. Nothing I try seems to work and I have checked to see whether anyone has answered this but can't find anything on it.
Thanks :)
You're using the wrong function. In this line:
self.inventory.update(room[self.room_number]['items'][item])
update will essentially add all the keys and values from room[self.room_number]['items'][item] to self.inventory.
Instead, you want to assign the item dictionary as a value in the inventory dictionary, with a key for that item.
So you should do this:
self.inventory[item] = room[self.room_number]['items'][item]
Or better yet, as #MKesper points out, you should pop the key so that it's removed from the room's items dictionary when you put it into the inventory:
self.inventory[item] = room[self.room_number]['items'].pop(item, None)
This will attempt to get item out of the dictionary, and if it's not found None will be returned instead. If you remove None you'll instead have a KeyError, and depending on how confident you are in item being a valid key, a KeyError might be better to catch the unusual cases when incorrect keynames have appeared.
Docs on dict.pop
You can use update method:
dict1.update(dict2)

Categories