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])
Related
Hi I am reading data from file in the class Patients and passing the content to appointment class method.
when the content is split such that content[0] has ['130', 'Ali', 'Male', '22', 'Cough'] so I am putting these values and setting the Patient class properties. This is done in for loop so all objects from file read are added to list of Patient class. But in doing so it is repetitively adding only one row of data.
Below is the code:
//Text file Data:
ID PatientName Gender Age Disease
130 Ali Male 22 Cough
132 Annile Female 23 Corona
133 sam Male 24 Fever
I want list of patients to store 130-132-133 but instead it stores only 133 at all three positions of list. Dont know if object creation or passing for Patient class is an issue
//Patient.py
class Patients:
def __init__(self):
self.patient_id = ""
self.patient_name = ""
self.patient_age = ""
self.patient_gender = ""
self.patient_disease = ""
def read_patient_file(self):
with open('PatientRecord.txt') as f:
content = f.readlines()
content = [x.strip() for x in content]
del content[0] // first row is of column names so removing it
return content
//Appointment.py
def patientProgram(list_patient):
Flag = True
pat1 = Patients()
while Flag:
print("\nPress 1. To Create Patient Record ")
print("Press 2. To View Patient Records ")
print("Press 6. To Read Patient Record From File ")
x = int(input("Please input from Menu Displayed Above which Operation to perform:"))
if x == 1:
list_patient.append(AddPatient())
elif x == 2:
print("**********")
print("Total Records in Memory for Patients:" + str(len(list_patient)))
for pat in list_patient:
print(f'patient_id = {pat.patient_id} for object {pat}')
elif x == 6: // this condition gives issue
content = []
content = pat1.read_patient_file() // content gets 3 rows of data from text file
j = 0
for i in content:
pat_id, name, gender, age, disease = str(content[j]).split()
print("FirstID: " + str(j)+ str(pat_id))
pat1.set_patient_record(pat_id, name, gender, age, disease)
list_patient.append(pat1)
j=j+1
print("Total Records for Patients in memory : " + str(len(list_patient)))
from Patients import Patients
if __name__ == "__main__":
list_patient = []
Flag = True
while Flag:
print("\nPress 1. For Patient Options ")
print("Press 2. For Doctor Options ")
print("Press 3. To Exit Program ")
x = int(input("Please Select From Menu:"))
if x == 1:
patientProgram(list_patient)
elif x==3:
break
You're only creating one Patients object. For each record in the file, you modify the pat1 object and append it to the list_patient list. So all the list elements are the same object.
You need to create a new object for each record in the file, not one object at the beginning.
Also, the read_patient_file() function should be a class method, since it doesn't use self for anything.
class Patients:
def __init__(self):
self.patient_id = ""
self.patient_name = ""
self.patient_age = ""
self.patient_gender = ""
self.patient_disease = ""
#classmethod
def read_patient_file(cls):
with open('PatientRecord.txt') as f:
content = f.readlines()
content = [x.strip() for x in content]
del content[0] // first row is of column names so removing it
return content
def patientProgram(list_patient):
Flag = True
while Flag:
print("\nPress 1. To Create Patient Record ")
print("Press 2. To View Patient Records ")
print("Press 6. To Read Patient Record From File ")
x = int(input("Please input from Menu Displayed Above which Operation to perform:"))
if x == 1:
list_patient.append(AddPatient())
elif x == 2:
print("**********")
print("Total Records in Memory for Patients:" + str(len(list_patient)))
for pat in list_patient:
print(f'patient_id = {pat.patient_id} for object {pat}')
elif x == 6: // this condition gives issue
content = []
content = Patients.read_patient_file() // content gets 3 rows of data from text file
j = 0
for i in content:
pat1 = Patients()
pat_id, name, gender, age, disease = str(content[j]).split()
print("FirstID: " + str(j)+ str(pat_id))
pat1.set_patient_record(pat_id, name, gender, age, disease)
list_patient.append(pat1)
j=j+1
print("Total Records for Patients in memory : " + str(len(list_patient)))
Reading in the data text file,
Running loops to check criteria for valid and invalid student numbers.
Then trying to write 2 text files, one for the invalid student numbers and one for the valid student numbers
This far everything works accept no text files written and no data written to text files at the end
Here is the Script so far
inputList = []
outputList = []
def FileOpen(myList):
#try:
count=0
INFILE=open("data.txt", "r")
for line in INFILE:
myList.append(line.rstrip())
count+=1
INFILE.close()
return count
#except:
# print("File could not be found")
# exit()
FileOpen(inputList)
print(FileOpen(inputList),"number of lines read from file")
def AnalyseStudents(rawStudents,totalStudents):
for entry in rawStudents:
amountOfDigits = len(entry)
testOfDigits = entry.isdigit()
def inValid1(val1,val2):
answ = val1 != 8 and val2 != True
return answ
inValidResult1=(inValid1(amountOfDigits,testOfDigits))
def Valid1(val1,val2):
answ = val1 == 8 and val2 == True
return answ
validResult1=(Valid1(amountOfDigits,testOfDigits))
if inValidResult1:
print(entry, " is an INVALID student number")
elif validResult1:
a=entry[0]
b=entry[1]
c=entry[2]
d=entry[3]
e=entry[4]
f=entry[5]
g=entry[6]
h=entry[7]
sum = float((a*8)+(b*7)+(c*6)+(d*5)+(e*4)+(f*3)+(g*2)+(h*1))
result = sum%11
def inValid2 (val):
answ = val != 0
return answ
inValidResult2=(inValid2(result))
def Valid2 (val):
answ = val == 0
return answ
validResult2=(Valid2(result))
if validResult2:
print(entry, " is an VALID student number")
elif inValidResult2:
print(entry, " is an INVALID student number")
totalStudents
AnalyseStudents(inputList,outputList)
def Write(outList):
if outList == (" is an VALID student number"):
OUTFILE1=open("ValidNumbers.txt","w")
for validResult in outList:
OUTFILE1.write(validResult+"\n")
OUTFILE1.close()
elif outList == (" is an INVALID student number"):
OUTFILE2=open("InvalidNumbers.txt","w")
for inValidResults in outList:
OUTFILE2.write(inValidResults+"\n")
OUTFILE2.close()
Write(outputList)
print("See output files for more details")
Your equality statements are wrong
if outList == (" is an VALID student number"):
...
elif outList == (" is an INVALID student number"):
The outList is a list but you are comparing it to strings. Put a debug breakpoint at those if statements and decide what you want.
I'm still working my way through this, but for the first function, you can use list comprehension and a couple of other Python functions. Commentary is included.
inputList = []
outputList = []
# Change parameter to the name of the file you want to open.
# Here, we can just make the parameter optional and pass your
# text file name by default.
def FileOpen(filename="data.txt"):
# Using with keeps the open file in context until it's finished
# it will then close automatically.
with open(filename, "r") as INFILE:
# Reach all the data at once and then try to decode it.
data = INFILE.read()
try:
data = data.decode("utf-8")
# If data can't be decoded, then it doesn't have that attribute.
# Catch that exception
except AttributeError:
pass
# Python 3 has a string method called .splitlines() that makes
# splitting lines a little simpler.
myList = [line for line in data.splitlines()]
# We'll return two values: The length (or count) of the list
# and the actual list.
return len(myList), myList
# We set up two variables for intake of our count and list results.
count, myList = FileOpen()
print("{} number of lines read from file".format(count))
EDIT: I don't know what the last part of your code is aiming to do. Maybe compare student count to valid entries? Here's the middle part. I moved the function outside and made it evaluate either valid or invalid in one fell swoop.
def is_valid(entry_value):
"""Validate current entry."""
if len(entry_value) != 8 and entry_value.isnumeric():
return False
return True
def AnalyseStudents(rawStudents, totalStudents):
for entry in rawStudents:
# Our new function will return True if the entry is valid
# So we can rework our function to run through the True condition
# first.
if is_valid(entry):
entry_sum = entry[0] * 8
entry_sum += entry[1] * 7
entry_sum += entry[2] * 6
entry_sum += entry[3] * 5
entry_sum += entry[4] * 4
entry_sum += entry[5] * 3
entry_sum += entry[6] * 2
entry_sum += entry[7] * 1
if entry_sum % 11 == 0:
print(entry, " is an VALID student number")
else:
print(entry, " is an INVALID student number")
else:
print(entry, " is an INVALID student number")
AnalyseStudents(inputList, outputList)
I've been searching for a solution for hours, but I can't find anything that helps. I'm having a problem converting a list of tuples into a dictionary. I get this error: 'ValueError: dictionary update sequence element #320 has length 1; 2 is required.' Here is a small example of the list of tuples:
[('Heat_equation', 262), ('Portal:Tertiary_Educatio', 262), ('Help:Wiki_markup_example', 262), ('Quantum_mechanics', 262), ('IB_Language_A:_English_Language_and_Literature_Course_Materia', 261), ('Pulmonary_Plethor', 261)]
This is what I want:
{'Heat_equation': 262, 'Portal:Tertiary_Educatio': 262, 'Help:Wiki_markup_example': 262, 'Quantum_mechanics': 262, 'IB_Language_A:_English_Language_and_Literature_Course_Materia': 261, 'Pulmonary_Plethor': 261}
The length is 2 though right? I'm not sure why I'm getting an error. Here is the function where I'm trying to convert the list of tuples into a dictionary:
import urllib.request
import json
import re
def get_url(url):
text = urllib.request.urlopen(url).read().decode()
return text
def get_choice():
try:
print("Select from the following options or press <?> to quit:")
print("1. Display top 1000 articles and views.")
print("2. Display top 100 learning projects.")
choice = input()
choice = int(choice)
if 1 <= choice <= 2:
print()
return choice
except ValueError:
if choice == "":
return None
print("%s is not a valid choice.\n" % choice)
def display_json(text):
lst = []
dictionary = json.loads(text)
for item in dictionary['items']:
for article in item['articles']:
line = (article['article'], article['views'])
lst.append(line)
return lst
def convert_dict(lst):
d = dict()
[d[t[0]].append(t[1]) if t[0] in (d.keys())
else d.update({t[0]: [t[1]]}) for t in lst]
dictionary = {k: v[0] for k, v in d.items()}
return dictionary
def display_dict(dictionary):
print(dictionary)
def learning_project(dictionary):
lst_2 = []
for key, value in dictionary.items():
string = str(key)
match = re.findall(r'([^\/ ]+).*?\w+.*', string)
match.append(value)
tup = tuple(match)
lst_2.append(tup)
return lst_2
def convert(lst_2):
p = dict(lst_2)
print(p)
def main():
while True:
url = "https://wikimedia.org/api/rest_v1/metrics/pageviews/top/en.wikiversity/all-access/2018/01/all-days"
choice = get_choice()
if choice == None:
break
elif choice == 1:
text = get_url(url)
lst = display_json(text)
dictionary = convert_dict(lst)
display_dict(dictionary)
elif choice == 2:
text = get_url(url)
lst = display_json(text)
dictionary = convert_dict(lst)
lst_2 = learning_project(dictionary)
convert(lst_2)
main()
To explain the learning project function, I had a bigger dictionary I needed to parse. So I turned the key into a string and parsed the key with RegEx. I then appended the value to the key and that created rows of lists. Then I turned the rows of lists into tuples, and created a list of tuples. Now I'm just trying to turn this back into a dictionary, but it is not working. Any help is greatly appreciated!
if you are getting errors with p = dict(lst_2) then your input data is not compliant with your requirement. You could make the conversion more robust by ensuring that list elements are always a two entry tuple.
p = dict( (*t,None,None)[:2] for t in lst_2 or [])
This will not fix the data but it may allow you to move forward and perhaps detect the faulty data by finding None key or None values in the resulting dictionary.
data = [('Heat_equation', 262), ('Portal:Tertiary_Educatio', 262),
('Help:Wiki_markup_example', 262), ('Quantum_mechanics', 262),
('IB_Language_A:_English_Language_and_Literature_Course_Materia', 261),
('Pulmonary_Plethor', 261)]
mydict = dict(data)
I had this program in Python regarding baby names in Texas. Solved quite a bit of it, but got stuck in the counting part. I converted the list to the dictionary. The output has to be such that the program displays the top 5 most popular baby names in the time span provided by the user (begin year, end year).
def count_names(file_data, begin, end, sex):
import operator as op
x=[]
c=[]
a=[]
t=[]
number_names = 5
for d in range (begin,end+1):
x.append(str(d))
for y in file_data:
if y[5:9] in x:
c.append(y)
for q in c:
p=q.split(',')
if (p[1]=='M'):
t.append(p)
elif(p[1]=='F'):
a.append(p)
if(sex=='M'):
dm={}
for h in t:
dm[h[3]]=h[4]
elif(sex=='F'):
df={}
for j in a:
df[j[3]]=j[4]
def main():
#Open the data file and save the data in a list called file_data.
#Each element of the list is a string in the format:
# 'TX,GENDER,YEAR_OF_BIRTH,BABY_NAME,OCCURRENCES\n'
file_data = open('TX19010-2016.csv').readlines()
sex = 'M'
cmd = ''
while cmd != 'quit()':
cmd = input('> ')
if cmd == 'girl':
sex = 'F'
elif cmd == 'boy':
sex ='M'
elif cmd != 'quit':
years = cmd.split()
begin = int(years[0])
if len(years) > 1:
end = int(years[1])
else:
end = begin
count_names(file_data, begin, end, sex)
main()
I am trying to print the results from all 3 names that are input, in a dictionary format. Current code below only prints out the last name. The 2 lines commented out (#) are what I was trying to change around to get it to work, clearly not doing it correctly.
def name():
count = 0
while (count < 5):
d = {}
qs = dict(Fname='first name', Lname='last name')
for k,v in qs.items():
d[k] = input('Please enter your {}: '.format(v))
#d['first name'].append(v)
#d['last name'].append(v)
count += 1
print(d)
name()
A few things that I'd change:
append each record (dictionary) to a list of entries.
(optional) Use a for-loop rather than a while as less lines of code.
return the entries list, rather than print it as it is a function so I like to have outputs.
So here's the corrected code:
def name():
entries = []
for count in range(5):
d = {}
qs = dict(Fname='first name', Lname='last name')
for k, v in qs.items():
d[k] = input('Please enter your {}: '.format(v))
entries.append(d)
return entries
print(name())
For testing purpose, I modified it to just except 2 entries, but we can still see that it works:
Please enter your last name: fish
Please enter your first name: bowl
Please enter your last name: cat
Please enter your first name: mat
[{'Lname': 'fish', 'Fname': 'bowl'}, {'Lname': 'cat', 'Fname': 'mat'}]
Hope! you got it right from Martijin Comments, For reference to other adding this code:
def name():
count = 0
listOfDict = [] #creating empty list
for count in range(3):
dict = {}
qs = dict(Fname = 'first name', Lname = 'last name' )
for k,v in qs.items():
d[k] = input('please enter your {}: '.format(v))
listOfDict.append(d) # adding each item to the list.
count += 1
print listOfDict
name()
This should work:
def name():
count = 0
while (count < 5):
d = {}
qs = dict(Fname='first name', Lname='last name')
for k,v in qs.items():
a = input('Please enter your {}: '.format(v))
d[v] = a
count += 1
print(d['first name'],d['last name'])
name()
You can use defaultdict to automatically create lists to store each entered value. The main idea is that you want to append each entered value to a collection of some type (e.g. list).
from collections import defaultdict
number_of_entries = 3
dd = defaultdict(list)
for _ in range(number_of_entries):
for key in ('first name', 'last_name'):
dd[key].append(input('please enter you {}: '.format(key)))
>>> print(dict(dd))
{'first name': ['Adam', 'Milton', 'Irving'],
'last_name': ['Smith', 'Friedman', 'Fisher']}