Count the number of values in a dictionary? - python

I created a dictionary and want to create a function called count_type that will take that dictionary and return another dictionary that is called count. This function takes in a menu (dictionary) and returns a count (dictionary) that maps each item type to the count of how many items of that type exist in the menu.
The new dictionary starts looking like:
count = {"Entrees": 0, "Salads": 0, "Sides": 0,
"Kid's Meals": 0, "Desserts": 0, "Drinks": 0}
I want the end result to be the same dictionary but the 0's to be changed to the count of how many times there is a key:value with the value 'Entrees' etc in the original dictionary. an example of what I would like the output to look like:
count = {"Entrees": 3, "Salads": 15, "Sides": 3,
"Kid's Meals": 6, "Desserts": 4, "Drinks": 5}
So far I have the code:
def count_type(carte):
count = {"Entrees": 0, "Salads": 0, "Sides": 0,
"Kid's Meals": 0, "Desserts": 0, "Drinks": 0}
menu = read_file("menu1.csv")
ent = 0
salad = 0
side = 0
kid = 0
dessert = 0
drink = 0
for value in menu:
if value == 'Entrees':
ent += 1
elif value =='Salads':
salad += 1
elif value =='Sides':
side +=1
elif value== "Kid's Meals":
kid +=1
elif value =='Desserts':
dessert +=1
else:
drink +=1
This loop only gives me a count for drink of 46 which is all the values. How do I do this?
The read_file function that I have created already is:
def read_file(filename):
file = open("menu1.csv", "r", encoding='utf-8-sig')
file.readline()
menu = {}
for line in file:
line = line.rstrip('\n')
line = line.split(',')
item = line[0]
price = float(line[1])
cal = int(line[2])
typ = str(line[3])
lst= (price, cal, typ)
tup = tuple(lst)
menu[item] = tup
return menu
print(menu) returns a long dictionary:
{'Chic-fil-A Chicken Sandwich': (3.75, 440, 'Entrees'),
'Chic-fil-A Deluxe Sandwich': (4.45, 500, 'Entrees'),
'Spicy Chicken Sandwich': (3.99, 460, 'Entrees'),
'Spicy Deluxe Sandwich': (4.69, 550, 'Entrees'),
'Grilled Chicken Sandwich': (5.15, 320, 'Entrees'),
'Grilled Chicken Club': (6.55, 460, 'Entrees')
Where some are 'Entrees', 'Salads', etc.

I recommend you try: count[value] += 1 in for value in menu loop
Update: you should edit your loop
for k,v in menu.items():
count[v[2]] += 1

Your code doesn't work because you're iterating over the keys of your menu dictionary, which is the names of the items (e.g. 'Spicy Chicken Sandwich'), but you're expecting to have an item type (e.g. "Entrees").
To fix this you need to change your loop. I'd suggest:
for _, _, value in menu.values():
if value == 'Entrees':
...
I'd note that the name value is not very clear what kind of value it is, especially when you're getting a bunch of other data from the dictionary (and throwing them into the _ variable that will be ignored). Unpacking into more clearly named variables, like price, cal, typ again, might make the code clearer.
It might also be a good idea to match 'Drinks' explicitly, rather than letting any invalid types fall in there. You could have your code raise an exception if it gets an unknown type instead:
elif value == 'Drinks':
drinks += 1
else:
raise ValueError("Unknown menu item type: {}".format(typ))

In your for loop
for value in menu:
instead of checking against value, check against the following
for value in menu:
count[menu[value][2]] += 1
and as mentioned above, instead of creating seperate counters for each variables, you can make use of the already created count dictionary by using
count["Entrees"] += 1

Related

How to iterate through a list of class objects and total up how many attributes are the same?

I know the title is worded weird, I can't think of how to best word this.
Basically I have to create a survey in python with an option to view statistics of all of the submissions. I'm storing the submissions as objects in a list.
One of the questions in the survey are radio buttons to choose your ethnicity, and I want to total up how many of each ethnicity there is.
I did get it to work using this:
totalSubmissions = 0
totalWhite = 0
totalBlack = 0
totalAsian = 0
totalMixed = 0
totalOther = 0
for s in submissions:
submissionList.insert(END, s.getInfo())
totalSubmissions += 1
if s.ethnicity == "White":
totalWhite += 1
elif s.ethnicity == "Black":
totalBlack += 1
elif s.ethnicity == "Asian":
totalAsian += 1
elif s.ethnicity == "Mixed":
totalMixed += 1
elif s.ethnicity == "Other":
totalOther += 1
But this feels really inefficient and I'm sure there must be a better way to do this using iteration or something.
I assume that you have a survey class as below
class Survey:
def __init__(self, *args, **kwargs):
# other attrs ..
self.ethnicity = kwargs.get("ethnicity")
and then there is a list of submissions objects for example
submission_list = [
Survey(ethnicity="White"),
Survey(ethnicity="Black"),
Survey(ethnicity="Asian"),
Survey(ethnicity="Mixed"),
Survey(ethnicity="Other"),
Survey(ethnicity="White"),
Survey(ethnicity="White"),
Survey(ethnicity="Other"),
]
Now, you can get the total submission count as
total_submission = len(submission_list)
print("total_submission: ", total_submission)
And then define a dict for count of specific ethnicity, loop through the submissions list and check increase the ethnicity of the matched dict key.
total_dict = {
"White": 0,
"Black": 0,
"Asian": 0,
"Mixed": 0,
"Other": 0,
}
for s in submission_list:
total_dict[s.ethnicity] += 1
print("total_dict: ", total_dict)
What is SubmissionList? their is no function in for it. Relook at your code. There are many variables not defined.

In a list, perform a task depending on the index values?

Ok, so I have been trying to get specific indexes in my list "beans" to perform a task depending on the value of that index.
Here is the code:
def dude():
beans = ['639', '939']
bun = 0
heyo_beans = beans[bun]
while bun in range(len(beans)):
while bun in range(len(beans)):
try:
b = heyo_beans.index('639')
except ValueError:
print("Do Nothing")
break
else:
print("Do something with variable b")
break
bun = bun + 1
print(bun)
print(beans[1])
dude()
OUTPUT:
Do something with variable b
1
Do something with variable b
2
939
I should be getting:
Do something with variable b
1
Do Nothing
2
939
"Do Nothing" should appear the second go around as the index changed to index 2, which is 939.
The final output of 939 is to verify that bean index 1 is indeed 939.
Any ideas?
Another example would be:
list = ['111', '222', '333']
#goes through the list in a while loop, each time adding +1 index, for range in length
if list index = 111:
"Perform task A"
elif list index = 222:
"Perform task B"
elif list index = 333:
"Perform task C"
else:
"Do Nothing"
list index = index + 1
Any suggestions on how to make this work?
This also does not work:
def dude():
list_to_beans = ['639', '939']
bun = 0
heyo_beans = list_to_beans[bun]
while bun in range(len(list_to_beans)):
for bun in list_to_beans:
if heyo_beans == '639':
print("Do something")
else:
print("Do nothing")
bun = bun + 1
print(bun)
dude()
OUTPUT:
Do something
Do something
Should say:
Do something
Do nothing
2
You're making this way more complicated than it needs to be. Just use an ordinary for loop to iterate over all the elements of the list. You're confusing indexes with the elements.
Since the list contains strings, you have to compare with strings, not numbers.
mylist = ['111', '222', '333']
for item in mylist:
if item == '111':
"Perform task A"
elif item == '222':
"Perform task B"
elif item == '333':
"Perform task C"
else:
"Do Nothing"
Answer:
def dude():
list_to_beans = ['639', '939']
bun = 0
heyo_beans = list_to_beans[bun]
for heyo_beans in list_to_beans:
if heyo_beans == '639':
print("Do something")
else:
print("Do nothing")
bun = bun + 1
print(bun)
dude()
OUTPUT:
Do something
Do Nothing
1

How to display a list of tuples and count the same number of elements

input
def inisial(daftar):
daftar = (
"Michael","Viny","Aurelio","Michael",
"Felix","Kevin","Vincen","Vincen","Michael")
inisial(daftar)
output:
Michael
Viny
Aurelio
Michael2
Felix
Kevin
Vincen2
Vincen3
Michael3
I assume you want to count the number of occurences for each name. If so, you can do it like this. If you want the output to be different you can, of course, change the return format of the dictionary.
def inisial(daftar):
d = {}
for daft in daftar:
if daft not in d:
d[daft] = 0
else:
d[daft] += 1
return d
daftar = (
"Michael","Viny","Aurelio","Michael",
"Felix","Kevin","Vincen","Vincen","Michael")
inisial(daftar)
Output:
{'Michael': 2, 'Viny': 0, 'Aurelio': 0, 'Felix': 0, 'Kevin': 0, 'Vincen': 1}
You need to count frequencies of entries in your list and use this frequencies in returend list.
def inisial(daftar):
freqs = {}
for name in daftar:
freqs[name] = freqs.get('name', 0) + 1
ret = []
for name in daftar:
freq = freqs[name]
if freq == 1:
ret.append(name)
elif freq > 1:
ret.append(name + str(freq))
return ret
In addition to #Sandertjunh's answer, you could use collections.Counter.
you can solve the problem with the following code.
daftar = ("Michael", "Viny", "Aurelio", "Michael",
"Felix", "Kevin", "Vincen", "Vincen", "Michael")
temp_dict = {}
for name in daftar:
if temp_dict.get(name):
temp_dict[name] += 1
else:
temp_dict[name] = 1
if temp_dict[name] > 1:
print('%s%d' % (name, temp_dict[name]))
else:
print(name)

Finding the top 10 and converting it from centimeters to inches - Python

I am reading data from file, like listed below, it is a .dat file:
1
Carmella Henderson
24.52
13.5
21.76
2
Christal Piper
14.98
11.01
21.75
3
Erma Park
12.11
13.51
18.18
4
Dorita Griffin
20.05
10.39
21.35
The file itself contains 50 records. From this data I need the person number, name and the first number, like so:
1 #person number
Marlon Holmes #Name
18.86 # First number
13.02 # Second Number
13.36 # Third Number
I already have code to read the data however I unable to get the top 10 results based on the #First number
The #First number in the Top 10 currently is in centimeters but needs to be converted to inches, I am unsure on how to combine the top 10 and conversion into one alongside the reading of the data
Code that reads the data:
with open('veggies_2016.txt', 'r') as f:
count = 0
excess_count = 0
for line in f:
if count < 3:
print(line)
count += 1
elif count == 3 and excess_count < 1:
excess_count += 1
else:
count = 0
excess_count = 0
As mentioned the code reads the file, like so #Person number, #name and #first number, but #first number needs to be converted to inches and then all of the data needs to be sorted to find the top 10
This process will also have to be repeated for #second number and #third number however they are separate in terms of their code from #first number
I have tried to read the data then append to a list and sort it and convert it from that but with no success, any help would be appreciated
Whole code:
from collections import OrderedDict
from operator import itemgetter
import pprint
def menu():
exit = False
while not exit:
print("To enter new competitior data, type new")
print("To view the competition score boards, type Scoreboard")
print("To view the Best Overall Growers Scoreboard, type Podium")
print("To review this years and previous data, type Data review")
print("Type quit to exit the program")
choice = raw_input("Which option would you like?")
if choice == 'new':
new_competitor()
elif choice == 'Scoreboard':
scoreboard_menu()
elif choice == 'Podium':
podium_place()
elif choice == 'Data review':
data_review()
elif choice == 'quit':
print("Goodbye")
raise SystemExit
"""Entering new competitor data: record competitor's name and vegtables lengths"""
def competitor_data():
global competitor_num
l = []
print("How many competitors would you like to enter?")
competitors = raw_input("Number of competitors:")
num_competitors = int(competitors)
for i in range(num_competitors):
name = raw_input("Enter competitor name:")
Cucumber = raw_input("Enter length of Cucumber:")
Carrot = raw_input("Enter length of Carrot:")
Runner_Beans = raw_input("Enter length of Runner Beans:")
l.append(competitor_num)
l.append(name)
l.append(Cucumber)
l.append(Carrot)
l.append(Runner_Beans)
competitor_num += 1
return (l)
def new_competitor():
with open('veggies_2016.txt', 'a') as f:
for item in competitor_data():
f.write("%s\n" %(item))
def scoreboard_menu():
exit = False
print("Which vegetable would you like the scoreboard for?")
vegetable = raw_input("Please type either Cucumber, Carrot or Runner Beans:")
if vegetable == "Cucumber":
Cucumber_Scoreboard()
elif vegetable == "Carrot":
Carrot_Scoreboard()
elif vegetable == "Runner Beans":
Runner_Beans_Scoreboard()
def Cucumber_Scoreboard():
exit = True
print("Which year would you like the Scoreboard from?")
scoreboard = raw_input("Please type a year:")
if scoreboard == "2015":
cucumber_veg_2015()
elif scoreboard == "2014":
cucumber_veg_2014()
elif scoreboard == "2016":
cucumber_veg_2016()
def cucumber_veg_2016(cm):
return float(cm) / 2.54
names = OrderedDict([('Competitor Number', int),
('Competitor Name', str),
('Cucumber', cucumber_veg_2016),
('Carrot', float),
('Runner Bean', float)])
data = []
with open('veggies_2016.txt') as fobj:
while True:
item = {}
try:
for name, func in names.items():
item[name] = func(next(fobj).strip())
data.append(item)
except StopIteration:
break
pprint.pprint(sorted(data, key=itemgetter('Cucumber'))[:10])
Solution
Reading the data into a list of dictionaries would work:
from collections import OrderedDict
from operator import itemgetter
import pprint
def to_inch(cm):
return float(cm) / 2.54
names = OrderedDict([('person_number', int),
('name', str),
('first', to_inch),
('second', float),
('third', float)])
data = []
with open('veggies_2016.txt') as fobj:
while True:
item = {}
try:
for name, func in names.items():
item[name] = func(next(fobj).strip())
data.append(item)
except StopIteration:
break
pprint.pprint(sorted(data, key=itemgetter('first'))[:10])
Output:
[{'first': 4.76771653543307,
'name': 'Erma Park',
'person_number': 3,
'second': 13.51,
'third': 18.18},
{'first': 5.897637795275591,
'name': 'Christal Piper',
'person_number': 2,
'second': 11.01,
'third': 21.75},
{'first': 7.893700787401575,
'name': 'Dorita Griffin',
'person_number': 4,
'second': 10.39,
'third': 21.35},
{'first': 9.653543307086613,
'name': 'Carmella Henderson',
'person_number': 1,
'second': 13.5,
'third': 21.76}]
In Steps
This helper function converts centimeters into inches:
def to_inch(cm):
return float(cm) / 2.54
We use an ordered dictionary to hold the names for the different items we want to read in order. The value is a function that we use to convert the read value for each item:
names = OrderedDict([('person_number', int),
('name', str),
('first', to_inch),
('second', float),
('third', float)])
We start with an empty list:
data = []
And open our file:
with open('veggies_2016.txt') as fobj:
We do something without a defined end and create a new dictionary item each time:
while True:
item = {}
We try to read from the file until it is finished, i.e. until we get a
StopIteration exception:
try:
for name, func in names.items():
item[name] = func(next(fobj).strip())
data.append(item)
except StopIteration:
break
We go through the keys and values of our order dictionary names and call each
value, i.e. the function func() on the next line we retrieve with next().
This converts the entry into the desired datatype and does the cm-inch conversion for first. After reading all items for one person, we append the dictionary to the list data.
Finally, we sort by the key first and print out the 10 to entries
(my example file has less than 10 entries):
pprint.pprint(sorted(data, key=itemgetter('first'))[:10])
Integration with your code:
You need to put the code into the function podium_place():
def cucumber_veg_2016(cm):
return float(cm) / 2.54
def podium_place():
names = OrderedDict([('Competitor Number', int),
('Competitor Name', str),
('Cucumber', cucumber_veg_2016),
('Carrot', float),
('Runner Bean', float)])
data = []
with open('veggies_2016.txt') as fobj:
while True:
item = OrderedDict()
try:
for name, func in names.items():
item[name] = func(next(fobj).strip())
data.append(item)
except StopIteration:
break
sorted_data = sorted(data, key=itemgetter('Cucumber'), reverse=True)
for entry in sorted_data[:10]:
for key, value in entry.items():
print key, value
print
menu()
At the end you need to call menu(). Also, if top mean largest first, you need sort reverse (see above).
I would read them as a record at a time. You can put that functionality in a function that you call several times with the same file. It can return a None when you reach the end of the file. It will return a tuple with all values for a given record (including conversions). You can then use sorted to sort the list of records using any one of the values from each record.
def read_record(fid):
id = fid.readline()
# At the end of the file
if id is None:
return None
name = fid.readline()
# Perform the conversion
number1_inches = float(fid.readline()) / 2.54
number2 = float(fid.readline())
number3 = float(fid.readline())
return (id, name, number1_inches, number2, number3)
with open('filename.txt', 'r') as fid:
records = list()
while True
new_record = read_record(fid)
# Stop if we hit the end of the file
if new_record is None:
break
records.append(new_record)
# Now sort the records based on the value of number1
records = sorted(records, key=lambda x: x[2])

Compute bill for a super market

Below is the code to compute the bill for the supermarket. Everything is ok but the issue is that I am told that this solution would not work if the input is only apple.
I do believe that the value of apple should be 0 since apples are not in the stock but still I believe there is something that I am not doing correct. Please help.
groceries = ["apple","banana", "orange",]
stock = {"banana": 6,
"apple": 0,
"orange": 32,
"pear": 15
}
prices = {"banana": 4,
"apple": 2,
"orange": 1.5,
"pear": 3
}
def computeBill(food):
total = 0
for item in food:
tot = prices[item] * stock[item]
print item, tot
total += tot
return total
computeBill(groceries)
I am just going to go off on my own with this answer and make suggestions, since it seems the specifications for your computeBill functionality are not well defined.
If the items are not in stock, and your instructor says it is not acceptable to return 0 in this case, then your other options are to raise an exception, or a sentinel value indicating an error state.
def computeBill(food):
total = 0
for item in food:
stock_count = stock[item]
if stock_count == 0:
raise ValueError("item %s is out of stock" % item)
tot = prices[item] * stock_count
print item, tot
total += tot
return total
Or if you don't want to raise an exception, you could return -1 if you feel that is not a valid total anyways:
if stock_count == 0:
return -1
There are some other problems with the function in how it calculates the list vs stock, but you said you didn't care about those right now.
I don't know why this wouldn't work. If your input was ['apple'], this would happen:
computeBill(['apple'])
total = 0
item = 'apple'
tot = price['apple'] * stock['apple']
tot = 2 * 0
print 'apple',0
total += 0
return total
return 0
Unless they expect to be able to pass in a single item without wrapping it in a list, so calling `computeBill('apple'). In that case, you'd have to do a type check at the beginning of your function. That could look like this
if type(food) is not list:
food = [food]
def compute_bill(food):
total=0
for item in food:
if stock[item]>0:
tot=prices[item]
total+=tot
stock[item]-=1
return total

Categories