Adding element to a dictionary in python? - python

I'm relatively new here, so please tell me if there is anything I should know or any mistakes I am making manner wise!
I am trying to add things onto a dictionary through random choice, but my code doesn't seem to work!
The file:
sports.txt
Soccer, Joshua
Lacrosse, Naome Lee
Soccer, Kat Valentine
Basketball, Huong
Tennis, Sunny
Basketball, Freddie Lacer
my code so far:
def sportFileOpen():
sportFile = open("sport.txt")
readfile = sportFile.readlines()
sportFile.close()
return(readfile)
def sportCreateDict(sportFile):
sportDict = {}
for lines in sportFile:
(sport, name) = lines.split(",")
if sport in sportDict:
sportDict[sport].append(name.strip())
else:
sportDict[sport] = [name.strip()]
return(sportDict)
def sportRandomPick(name, sport, sportDict):
if sport in sportDict:
ransport = random.choice(sportDict.keys())
sportDict[ransport].append(name)
print(name, "has been sorted into", ransport)
def main():
sportFile = sportFileOpen()
sportDict = sportCreateDict(sportFile)
name = input("Enter the name: ")
preferredSport = input("Which sport do they want? ")
sportRandomPick(name, preferredSport, sportDict)
main()
I am trying to allow a user to input their name and preferred group of sport, and whatever sport they prefer will have a higher chance of being randomly picked then the others (for example if Jason chooses soccer his chances of getting in soccer may double).
I don't expect anyone to write code for me, I know it's time consuming and you have better things to do! But can anyone maybe explain to me how I would go about doing this? I understand how to make random choices but I don't know how I would "double" the chances.
Also I keep getting this error when running my code: NameError: global name 'random' is not defined
I thought I was doing that part right but now i'm stuck. Can anyone give their two cents on this?

Try this:
def sportRandomPick(name, sport, sportDict):
if sport in sportDict:
ransport = random.choice(list(sportDict.keys()) + [sport]) # list of sports will contain preferred sport twice.
sportDict[ransport].append(name)
print(name, "has been sorted into", ransport)
This will increase chances of preferred sport to be picked by 2.
And don't forget to import random

I am assuming you are trying to use random.choice from python random.choice
you need to make sure it is imported at the top of your file:
import random
def sportRandomPick(name, sport, sportDict):
if sport in sportDict:
ransport = random.choice(sportDict.keys())
sportDict[ransport].append(name)
print(name, "has been sorted into", ransport)

Related

Curious about adding classes and how to add them

So basically I'm just trying to make a simple coding thing in python that incorporates classes, user input user output, conditionals, loops and arrays and so far I have everything added but for classes and loops. And im sort of lost on how I would add a class to this code ive looked around on how to do classes but im still a little confused. here is my code for my current program. a quick little summary about it is that its basically just a barbershop and depending on the inputs and the lists it will give you a certain haircutl. I know its a little simple but I just started programming not to long ago.
print("Welcome to Sids Barbershop")
Question = input("Would you like to get your haircut today")
if(Question == "yes"):
print ("Great come in and take a seat")
elif (Question == "no"):
print("Sounds good come back when your ready")
mylist = [['boy','14','curly'],
['girl','12','straight'],
['Man','28','wavy'],
['Woman','26''curly']]
record = []
gender = input("Do you consider yourself a boy,girl, man or woman")
record.append(gender)
age = input("How old are you")
record.append(age)
hair = input("what kind of hair type do you have")
record.append(hair)
search = int(input('Select and index to search an entry:'))
print(mylist[search])
if (search == 0):
print("alright so far so good would you like to get a fade and your hair cut by 2 inches?")
if(search == 1):
print("Ok so you have straight hair would you just like a trim?")
if(search == 2):
print("So you have wavy hair which is hard to deal with do you want to go bald?")
if(search == 3):
print('ok you have super long and curly hair do you want to try something new and perm your hair straight?')
i have tried to look up what a class was and how to incorporate it but I'm not to sure on how to.
A good use case for a class definition here would be the "customer" object that you're currently using the list class for. You can simplify the class definition with the #dataclass decorator:
from dataclasses import dataclass
#dataclass
class Customer:
gender: str
age: str
hair: str
Then replace the lists in mylist with Customers:
mylist = [
Customer('boy','14','curly'),
Customer('girl','12','straight'),
Customer('Man','28','wavy'),
Customer('Woman','26','curly'),
]
and define record as a Customer like this:
record = Customer(
input("Do you consider yourself a boy,girl, man or woman"),
input("How old are you"),
input("what kind of hair type do you have"),
)
Whereas with a list you can only access elements by their numeric index, your new Customer class has named attributes -- instead of record[1] to get the age the user entered, you can do record.age, etc.

Add more values in a list at once in Python

I'm a beginner in Python and I'm trying to solve this problem.
I'm trying to write a code where you can put your name and the amount that you want to donate.
The thing is, deppending on the amount of the donation you can have more chances to be the winner.
Eg. If you donate $10 (1 chance), $20(2 chances), $30(3 chances).
My biggest problem is because I can't figure out how to solve this problem when the person insert $30 its name goes to the list 3 times and so on. I tried to use "for..inrange():" but without any sucess. Can someone explain me how to do this?
from random import shuffle
from random import choice
list = []
while True:
name = str(input('Write your name: '))
donation = float(input('Enter the amount you want to donate.: $ '))
list.append(name)
print('You donated $ {}. Thank you {} for you donation!'.format(donation, name))
print('=-'*25)
print('[1] YES')
print('[2] NO')
answer = int(input('Would you like to make another donation? '))
if answer == 1:
continue
else:
shuffle(list)
winner = choice(list)
break
print('The winner was: {}' .format(winner))
First do not use the name of a built-in type as a (meaningless) variable name. Change list to entry_list.
For the particular problem
compute the quantity of chances;
make a list of the person's name that many times;
extend the entry list with that list of repeated name.
Code:
entry_list = []
while ...
...
chances = int(donation) // 10
entry_list.extend( [name] * chances )
An alternative to adding another loop with additional control flow, you can use list.extend() with a list expression:
num_chances = donation // 10
chances = [name] * num_chances
all_chances.extend(chances)
Note that list is a built-in python identifier, and it's not a good idea to overwrite it. I've used all_chances instead.
Rather than adding extra names to the list to represent the higher chance, you could use the donations as weights in the random.choices function:
from random import choices
names, donations = [], []
while True:
names.append(input('Write your name: '))
donations.append(float(input('Enter the amount you want to donate.: $')))
print(f'You donated ${donations[-1]}. Thank you {names[-1]} for your donation!')
print('=-'*25)
print('[1] YES')
print('[2] NO')
if input('Would you like to make another donation? ') != '1':
break
winner = choices(names, donations)[0]
print(f'The winner was: {winner}')
This allows for non-integer donations to be counted fairly -- e.g. if Bob donates $0.25 and Fred donates $0.50, the drawing will still work in a reasonable way. It also allows very large donations to be handled without tanking the performance of the program -- if you have one list entry per dollar donated, what happens if Elon donates $20B and Jeff donates $30B? (The answer is that your fan spins really fast for a while and then the program crashes because you can't create a list with 50 billion elements -- but this is not a problem if you simply have a list of two elements with large int values.)
Note that shuffle is not necessary if you're using random.choices (or random.choice for that matter) because those functions will already make a random selection from the list.
You can use a for loop to append the name to the list more than one time :
for i in range(donation//10):
list.append(name)
This code should do the job. Please follow good naming conventions as pointed out by others. I have changed the list variable to donations as it is forbidden to use keywords as variables.
I have included the name in donations int(name) // 10 times using the extend function as pointed out by others. You may change the number of times as you wish.
from random import shuffle
from random import choice
donations = []
makeDonation = True
winner = "Unknown"
while makeDonation:
name = str(input('Write your name: '))
donation = float(input('Enter the amount you want to donate.: $ '))
donations.extend([name for i in range ( int(donation) // 10)])
print('You donated $ {}. Thank you {} for you donation!'.format(donation, name))
print('=-'*25)
print('[1] YES')
print('[2] NO')
answer = int(input('Would you like to make another donation? '))
if answer == 2:
makeDonation = False
shuffle(donations)
winner = choice(donations)
print('The winner was: {}' .format(winner))

How do I put input into a python df?

Is it possible to put a user input into a df?
Here I am asking user to select the Town they are interested to find home prices, and return users with the lowest and highest home prices.
I have hardcoded the group "YISHUN" > When this is supposed to be user input
Also, the results are sorted pricing. How do I take the two values - the lowest and the highest?
Thank you so much!
sorted_df = df.sort_values("resale_price", ascending=True)
grouped_df = sorted_df.groupby("town")
grouped_df = grouped_df.get_group("YISHUN")
grouped_df = grouped_df[['resale_price']]
print(grouped_df)
It's actually really simple:
def get_hi_low(df, val):
dummy_df = df[df['town']==val]
return max(dummy_df['resale_price'].values), min(dummy_df['resale_price'].values)
val = input("Enter town name: ")
high, low = get_hi_low(df, val)
print(f'For town {val}, the highest value is: {high} and low is {low}')
Check if this works.
Edit:
Creating this as a function has a lot of benefits. In fact, whenever possible, you should usually code using functions.
So let's say you just don't have one but many users. For example:
town_list = ['Town_A', 'Town_B', 'Town_C']
Now you can loop around all these:
for town in town_list:
high, low = get_hi_low(df, town)
print(f'For town {town}, the highest value is: {high} and low is {low}')
So now for each town, it will result in the high and low value of the resale price.
And since in your case it's a user input? Well you can do it this way too:
while True:
town = input("Enter town name: ")
if town=='exit':
break
high, low = get_hi_low(df, town)
print(f'For town {town}, the highest value is: {high} and low is {low}')
In this case, user keep on inputting a town and for each case it gives a result. But remember code never stops in this case. The only case it will stop is when you input 'exit' and the loop ends. One last quick advice. This code will give error if the town name provided doesn't exist. Well for that case you can use try, except block. Well, look into what a try except is.
Hope this makes more sense. If you want to learn more about functions and even python extensively before jumping. I can suggest you some free courses and links to those.
val = input("Enter column name: ")
print(df.groupby([val])['YEAR'].count())
Yes, you can. Please try to give input before invoking group function. The above is a sample. I just tried out and I found it working.

python assign a variable to a randomly selected string

my children and I are messing with a random bedtime story generator. And apart from being amazed at how easy python is to use, we want to generate a random name for our protagonist, but for them to keep the same name throughout the story.
import random
names= ["Tim", "Ju Ju", "Legface", "Dusty", "Smudger"]
thing = ["princess", "elf", "fairy", "mermaid", "shoe maker"]
count = 0
while (count < 1):
print "Once upon a time there was a ",
print(random.choice(thing)),
print "whose name was ",
print(random.choice(names)),
so if the random name turns out to be Tim, I would like to continue the story as
print $thevariablethatisTim
print "was a very happy man"
I realise this is a trivial thing, but I can't seem to get it right and we are having such a good laugh at bedtime with this.
Thanks in advance
Neil
Just choose the name of your hero before you enter the while loop.
hero = random.choice(names)
# stuff
while some_condition:
# do stuff
print(hero) # or formatted string
# do other stuff
any time you want to refer to your protagonist, use the variable hero instead of calling random.choice again.

Python; List index out of range [address book task]

I'm currently studying Computer Science at GCSE level, and am nearing my first controlled assessment. Last week we moved onto learning about lists, but for the purpose of this weeks assignment, we need to create an improved version of our address book task using a 2D array. The purpose of the task is to allow the user to enter as many people as they require into an address book, and ask them for four pieces of information. This information is to be then printed onto the screen underneath.
Be that as it may, I'm encountering an error when entering more than one person into the address book, with the error list index out of range. I've read some posts on here already about the aforementioned error, but still don't seem to quite understand it fully. Any aid would be highly appreciated.
Here is my code thus far:
addressbook = ([])
number = int(input("How many people would you like in your address book:"))
for loop in range (0,number,1):
addressbook.append([(str(input("\nPlease enter your full name:")))])
addressbook.append([(str(input("Please enter your home address:")))])
addressbook.append([(str(input("Please enter your hometown:")))])
addressbook.append([(str(input("Please enter your mobile number:")))])
print("\nName:",addressbook[0][loop],"\nHomeaddress:",addressbook[1][loop],"\nHometown:",addressbook[2][loop],"\nMobile number:",addressbook[3][loop])
With the following error appearing:
Traceback (most recent call last):
File "C:\Users\Owner\Documents\Computer Science\Python\Address%20book.py", line 23, in <module>
print("\nName:",addressbook[0][loop],"\nHomeaddress:",addressbook[1][loop],"\nHometown:",addressbook[2][loop],"\nMobile number:",addressbook[3][loop])
IndexError: list index out of range
Rather than think of addressbook as a two-dimensional array of information about people, think of each dimension separately. An addressbook is a one-dimensional array of persons. Each person is, in turn, a one-dimensional array of information.
Bringing that thinking to our code can make the purpose much clearer:
# An address boook is an arary of persons
addressbook = []
number = int(input("How many people would you like in your address book:"))
# Create several persons, adding each to addressbook as we go:
for _ in range(number):
# Create one person:
person = []
person.append(str(input("\nPlease enter your full name:")))
person.append(str(input("Please enter your home address:")))
person.append(str(input("Please enter your hometown:")))
person.append(str(input("Please enter your mobile number:")))
# Add one person to addressbook
addressbook.append(person)
# Now addressbook has several persons
# Display addressbook, thinking of it as two-dim array
for loop in range(number):
print("\nName:",addressbook[loop][0],"\nHomeaddress:",addressbook[loop][1],"\nHometown:",addressbook[loop][2],"\nMobile number:",addressbook[loop][3])
# Display addressbook, thinking of it as array of persons:
for person in addressbook:
print("\nName:",person[0],"\nHomeaddress:",person[1],"\nHometown:",person[2],"\nMobile number:",person[3])
Other notes:
The statement addressbook = ([]) is identical to addressbook = []. Parentheses in that context do absolutely nothing.
Multi-dimensional arrays list the row number first, the column second. That is to say, the first number gets you to a row, and the 2nd number gets you to an element of that row. More simply, say addressbook[loop][0], not addressbook[0][loop].
The expression range(0, number,1) is identical to range(number), and the latter is easier to read.
In Python, if you need to assign a value but don't care about it further, use _, like so: for _ in range(number):.
The expression str(input(...)) is identical to the expression input(...), since input returns an object of type str. I left those alone because I suppose that verbose style is required by your instructor.
When the time comes, learn about breaking long expressions into multiple lines. Many people find that a line longer than about 80 characters is difficult to read.
You prompt the user "Please enter your full name" (emphasis added) each time. Presumably their name hasn't changed since the previous iteration of the loop. You are actually asking for some third party's full name. Try "Please enter their full name" or "Please enter this person's full name" or some such.
Finally, realize that computer programs will be read more often than they are written. This is true for professionally-maintained programs with hundreds of contributing programmers and also of one-off programs written by you for your own benefit. Use any means necessary to communicate effectively with the reader(s) of your program--comments, clear variable names, whitespace, whatever it takes.
First, Rob's explanation above is perfect for your assignment.
Now, I wanted to show you a few techniques, you can use, to make your life easier, without entering in OOP concepts and keeping the code as simple as possible, without error catching or whatsoever.
from collections import namedtuple
Person = namedtuple(
'Person',
('full_name', 'home_address', 'home_town', 'mobile_number')
)
person_print_template = '''
Full Name: {full_name}
Home Address: {home_address}
Home Town: {home_town}
Mobile Number: {mobile_number}'''
persons = []
number = int(input('How many people would you like in your address book: '))
for iteration in range(number):
full_name = input('\nFull name: ')
home_address = input('Home address: ')
home_town = input('Home town: ')
mobile_number = input('Mobile number: ')
person = Person(full_name, home_address, home_town, mobile_number)
persons.append(person)
for person in persons:
print(person_print_template.format(**person._asdict()))
collections.namedtuple is a way of defining really simple reusable objects and offers an _asdict() method which return a dictionary.
In python, putting ** in front of a dictionary allows you to unpack each of its dictionary keys and values which can be then passed, for example here, to a template, and str.format() will replace the "{key_name}" by its value.
Again this is a powerful way of formatting string output, especially when multi-line.=, either for the web or for command line output, like here.
Rob's answer, as Apero stated, is perfect. However as Apero addressed your format with functional programming, I'll address it in OOP (mostly because I love abstracting functional code! :D)
from collections import OrderedDict
# this is only necessary if you need your fields to always be in the
# same order when they're printed. Otherwise ignore and have Person
# inherit from dict
FIELDS = ["full name", "address", "hometown", "mobile number"]
class Person(OrderedDict): # see note above
def __init__(self, keys=None):
super().__init__() # this is magic that makes the OrderedDict work
if isinstance(keys, dict):
self.update(keys)
# this allows you to pass in a normal dict like you can for any
# other dict or ordered dict, and only prompt otherwise
else:
for key in keys:
self[key] = input("Please enter your %s: " % key)
def __str__(self):
"""The __str__ function describes how str(self) looks. I'm defining
it here to mimic the way Apero used his person_print_template string"""
output_strings = []
for key,value in self.items():
output_strings.append("{}: {}".format(key, value))
return "\n".join(output_strings)
# this is equivalently:
## return "\n".join(["{}: {}".format(key,value) for key,value in self.items()])
class AddressBook(list):
def __init__(self, size=None):
if size is None:
size = int(input("How many entries are in this address book? "))
for entry in range(size):
global FIELDS
self.append(Person(FIELDS))
def __str__(self):
return "\n\n".join([entry for entry in self])
# double spaced for readability
if __name__ == "__main__":
book = AddressBook()
print()
print(book)
# OUTPUT:
How many entries are in this address book? 2
Please enter your full name: Adam Smith
Please enter your address: 123 Some St.
Please enter your hometown: Eugene, OR
Please enter your mobile number: 555-867-5309
Please enter your full name: John Smith
Please enter your address: 987 Hello World, Ave.
Please enter your hometown: Camelot (tis a silly place)
Please enter your mobile number: 555-789-1234
full name: Adam Smith
address: 123 Some St.
hometown: Eugene, OR
mobile number: 555-867-5309
full name: John Smith
address: 987 Hello World, Ave.
hometown: Camelot (tis a silly place)
mobile number: 555-789-1234
You can certainly make changes in format to suit. I'd point you at the str.format method so you can do things like justify your strings beautifully
# # inside Person.__str__
for key,value in self.items():
global SCREENWIDTH # perhaps 50?
output_strings.append("{0}: {1:>{2}}".format(key,value, SCREENWIDTH - len(str(key)) - 1))
full name: Adam
address: blah
hometown: doohickey
mobile number: 1234
Possibly a flag on AddressBook.init that works as an alternate constructor given an existing list of Person objects.
class AddressBook(list):
def __init__(self, argument=None, _prompted=True):
if _prompted:
size = argument # just for clarity
self.from_prompt(size)
else:
lst = argument # just for clarity
self.from_list(lst)
def from_prompt(self, size):
# exactly as __init__ is above
def from_list(self, lst):
self.extend(lst)
Lots of fun stuff to be done with OOP. Personally I like them just because of Python's duck typing only becomes stronger when I can control both what kind of quack to listen to and what kind of quack to MAKE! :)
Use this instead
for loop in range (0,number,1):
addressbook.append([])
addressbook[-1].append([(str(input("\nPlease enter your full name:")))])
addressbook[-1].append([(str(input("Please enter your home address:")))])
addressbook[-1].append([(str(input("Please enter your hometown:")))])
addressbook[-1].append([(str(input("Please enter your mobile number:")))])
print("\nName:",addressbook[-1][0],"\nHomeaddress:",addressbook[-1][1],"\nHometown:",addressbook[-1][2],"\nMobile number:",addressbook[-1][3])
The problem with your code was you were using single dimension list. For every loop you are adding the items into addressbook so after 2 iterations of the loop it will look smthing like this
["name1","addr1","hmtown1","mob1","name2","addr2","hmtown2","mob2"]
So instead solution would be add an empty list for every iteration in loop and to that empty list we add the details so the structure would look like this
[["name1","addr1","hmtown1","mob1"],["name2","addr2","hmtown2","mob2"]]
In every iteration we access the last list by addressbook[-1] and then append the items to that last list, similarly accessing the items by using addressbook[-1][0].
Hope this helped you understand the problem.

Categories