Python List Index Ouf Of Range In IF Statement - python

So i have multiple patients' information stored in database.txt and i want to retrieve the data from the file into a list.
And the system prompt for patient's id to search and display other information of the patient such as Name, Age, Group & Zone.
However, i'm getting error from line 12, but the similar syntax in line 17 is able to run without problem.
search_keyword = input() # Asks for patient's name or id (either one)
with open("database.txt", "r") as database:
for data in database:
for patients in data.split('|'):
patient_details = []
for details in patients.split(','):
patient_details.append(details)
print(patient_details) # test
print(len(patient_details) # test
print(patient_details.index('Patient001')) # test
print(patient_details[4]) # test
if search_keyword == patient_details[0] or search_keyword == patient_details[4]: # error occured here, where it says list index out of range.
print("Name: " + patient_details[0])
print("Age: " + patient_details[1])
print("Group: " + patient_details[2])
print("Zone: " + patient_details[3])
print("ID: " + patient_details[4]) # no error here, patient_details[4] is able to display patient's id
database.txt
John,18,A,1,Patient001|Nick,20,F,9,Patient002
Test command for line 8,9, 10 and 11:
Line 8: [John, 18, A, 1, Patient001]
Line 9: 5
Line 10: 4
Line 11: IndexError: list index out of range
Can someone explain why this is happening, and any solutions regarding this issue without using any imported modules? Thank you for any assistance.

Imo a very good use-case for a named tuple:
from collections import namedtuple
text = "John,18,A,1,Patient001|Nick,20,F,9,Patient002"
# build database
Patient = namedtuple('Patient', ['name', 'age', 'group', 'zone', 'id'])
db = [Patient(*patient) for entry in text.split("|") for patient in [entry.split(",")]]
# Asks for patient's id
search_keyword = input("Please give an ID: ")
# query the database
result = [patient for patient in db if patient.id == search_keyword]
# or patient.id.startswith(), etc.
print(result)
Without any imported modules, you could use
text = "John,18,A,1,Patient001|Nick,20,F,9,Patient002"
# build database
db = [entry.split(",") for entry in text.split("|")]
search_keyword = input("Please give an ID: ") # Asks for patient's id
# query the database
result = [patient for patient in db if patient[4] == search_keyword]
print(result)

I see no flaw in the code. Although, I can point out a few ways to optimise it :
patient_details = dict()
with open("database.txt", "r") as database:
for data in database:
for patients in data.split('|'):
patients = patients.split(',')
patient_details[patients[4]] = patients[0:4]
search_keyword = input() # Asks for patient's id
if patient_details.get(search_keyword, None):
patient_detail = patient_details[search_keyword]
print("Name: " + patient_detail[0])
print("Age: " + patient_detail[1])
print("Group: " + patient_detail[2])
print("Zone: " + patient_detail[3])
print("ID: " + search_keyword)
Using map instead of a linear search would allow you to search optimally.

Related

Can I carry out a similar function to vlookup on a HTML table?

I'm trying to web scrape UFC fighters stats based on user input. I'm using beautiful soup and pandas. The idea is that the user input is matched to a fighters first and last name then returns their stats. Ideally I'd like to add the option of specifying which particular stat is required in a separate input. I've been able to pull the html table headers successfully but I don't know how to assign values to them which will correspond to the matching fighter name and print the associated value. In my code currently I'm splitting the fighter name input into first and last name, but I don't know how to then match them to the table data or how to return corresponding data. The data being returned currently is just the first line of results (fighter 'Tom Aaron') but no lookups or matching is being carried out. Are nested dictionaries the way to go? Any advice is greatly appreciated, this is my first python project so code is probably all over the place.
("Which fight do you want information on?"
input - Forrest Griffin
"What information do you want?:
input - Wins
"Forrest Griffin has won 8 times"
from bs4 import BeautifulSoup
import requests
import pandas as pd
website = "http://ufcstats.com/statistics/fighters?char=a&page=all"
response = requests.get(website)
response
soup = BeautifulSoup(response.content, 'html.parser')
results = soup.find('table', {'class' : 'b-statistics__table'}).find('tbody').find_all('tr')
len(results)
#print(results)
row = soup.find('tr')
print(row.get_text())
###attempting to split the table headers an assign
table = soup.find('table', {'class' : 'b-statistics__table'}).find('thead').find_all('tr')
#df=pd.read_html(str(table))[0]
#print(df.set_index(0).to_dict('dict'))
#firstname
first_name = str(results[0].find_all('td')[0].get_text())
print(first_name)
def first_names():
for names in first_name:
print(names)
return
#first_names()
last_name = results[1].find_all('td')[1].get_text()
print(last_name)
alias = results[1].find_all('td')[2].get_text()
if len(alias) == 0:
print("n/a")
else:
print(alias)
height = results[1].find_all('td')[3].get_text()
print(height)
weight = results[1].find_all('td')[4].get_text()
#print(weight)
wins = results[1].find_all('td')[7].get_text()
losses = results[1].find_all('td')[8].get_text()
draws = results[1].find_all('td')[9].get_text()
###split user input into list of first + second name
x = input("Which fighter do you want to know about?")
####print(str(first_name) + " " + str(last_name) + " has " + str(wins) + " wins, " + str(losses) + " losses and " + str(draws) + ".")
y = input("What do you want to know about?")
###if user input first name is in results row 1(Tom Aarons row) - still need to search through all result names
if x.split()[0] in str(results[1].find_all('td')[0].get_text()) and x.split()[1] in str(results[1].find_all('td')[1].get_text()) and y == "wins":
print(first_name+ " "+last_name+" has won " + wins + " times.")
if x.split()[1] in str(results[1].find_all('td')[1].get_text()):
print("ok")
else:
print('fail')
###Tom Test
print(x.split()[0])
###if input[1] = first_name and input2[2] == second_name:
if x.split()[1] == first_name:
print(x.split()[1])
if x.split()[0] in results[1] and x.split()[1] in results[1]:
print('wins')
else:
print("Who")
print(str(results[1].find_all('td')[0].get_text()))

Mysql json.dump() line break indentation for viewing

I am using the following line of code for executing and printing data from my sql database. For some reason that is the only command that works for me.
json_string = json.dumps(location_query_1)
My question is that when I print json_string it shows data in the following format:
Actions.py code:
class FindByLocation(Action):
def name(self) -> Text:
return "action_find_by_location"
def run (self, dispatcher: CollectingDispatcher,
tracker: Tracker,
doman: Dict[Text, Any])-> List[Dict[Text,Any]]:
global flag
location = tracker.get_slot("location")
price = tracker.get_slot("price")
cuisine = tracker.get_slot("cuisine")
print("In find by Location")
print(location)
location_query = "SELECT Name FROM Restaurant WHERE Location = '%s' LIMIT 5" % location
location_count_query = "SELECT COUNT(Name) FROM Restaurant WHERE Location = '%s'" % location
location_query_1 = getData(location_query)
location_count_query_1 = getData(location_count_query)
if not location_query_1:
flag = 1
sublocation_view_query = "CREATE VIEW SublocationView AS SELECT RestaurantID, Name, PhoneNumber, Rating, PriceRange, Location, Sublocation FROM Restaurant WHERE Sublocation = '%s'"%(location)
sublocation_view = getData(sublocation_view_query)
dispatcher.utter_message(text="یہ جگہ کس ایریا میں ہے")
else:
flag = 0
if cuisine is None and price is None:
json_string = json.dumps(location_query_1)
print(isinstance(json_string, str))
print("Check here")
list_a=json_string.split(',')
remove=["'",'"','[',']']
for i in remove:
list_a=[s.replace(i, '') for s in list_a]
dispatcher.utter_message(text="Restaurants in Location only: ")
dispatcher.utter_message(list_a)
What should I do se that the data is showed in a vertical list format (new line indentation) and without the bracket and quotation marks? Thank you
First of all, have you tried reading your data into a pandas object? I have done some programs with a sqlite database and this worked for me:
df = pd.read_sql_query("SELECT * FROM {}".format(self.tablename), conn)
But now to the string formatting part:
# this code should do the work for you
# first of all we have our string a like yours
a="[['hallo'],['welt'],['kannst'],['du'],['mich'],['hoeren?']]"
# now we split the string into a list on every ,
list_a=a.split(',')
# this is our list with chars we want to remove
remove=["'",'"','[',']']
# now we replace all elements step by step with nothing
for i in remove:
list_a=[s.replace(i, '') for s in list_a]
print(list_a)
for z in list_a:
print(z)
The output is then:
['hallo', 'welt', 'kannst', 'du', 'mich', 'hoeren?']
hallo
welt
kannst
du
mich
hoeren?
I hope I could help.

Using user input to search through an established dictionary

I'm trying to get through my first semester of Python and am struggling. My dictionary is correct however, I cannot get what I want. I need the user to input a patient ID and then the program will display the ID with the name linked to it in the dictionary as the name is the value. Then if the user enters an ID that is not in the dictionary the computer tells them so. If they enter done the program says DONE! When numbers are entered the program needs to continue asking the question until done is typed. Here is was I have so far:
patientinfo = {}
lines = open('PatientsNames.txt')
lines.readline()
for line in lines:
id=line[:8]
if id not in patientinfo:
endlastname = line.find(' ', 8)
lastname = line[8:endlastname]
firstname = line[endlastname+1:]
patientinfo[id] = lastname + ', ' + firstname
answer = raw_input("Enter an ID ('done' to exit)")
try:
if answer in patientinfo.keys():
print answer, patientinfo(val)
except:
if answer not in patientinfo.keys():
print 'No patient with that ID'
else:
if answer='done':
print 'DONE!'

Python - Write an array to csv / txt and then read

So if I have the following code:
database = []
Name = input("What's the members name?")
MT = input("What membership type?")
DOB = input("What is the member DOB?")
DJ = (now.day ,"/" , now.month, "/", now.year)
year1 = int(now.year)
month1 = int(now.month)
day1 = int(now.day)
ry = int(year1 + 1)
rm = month1
rd = day1
renewal = (day1, month1, year1 + 1)
details = ["Name:", Name, "Membership Type:", MT, "Date of Birth:", DOB, "Date Joined:", DJ,"Renewal Date:", renewal, "Renewal Year:", ry]
database.append(details)
menu()
How would I go about saving (database) to a text file / csv file to be read later.
I have tried pickle but the issue is I need to be able to get each part of the array seperate.
For example if I type:
print(database[1])
I will return all Names stored as "Name", however if I were to write the file using pickle when I bring it back in then
print (database[1])
now shows the entirety of the second user added. I need to be able to save (database) and have it in the same format when read back in.
Expected output using JSON or Pickle(assuming the first user inputted name as "Jeff" and second inputted name as "John")
print (database[1])
Jeff
John
Actual output:
["Name:", John, "Membership Type:", MT, "Date of Birth:", DOB, "Date Joined:", DJ,"Renewal Date:", renewal, "Renewal Year:", ry]
Sorry for the bad explanation I'm new to python.
It seems you are creating an array of records. Try accessing the data in this way:
print(database[0][1]) #[0] for the first record, [1] for second item
print(database[1][1]) #second user, second item

Subtract from an input appended list with a running balance output

Noob
I am trying to write a script that gives a running balance. I am messing up on the elementary declared functions of python.
I need it too:
accept a balance via input
append a list of transactions
take those out one by one in the order they were input
print a running total
use pyhtmltable to make the output in html table ready form for copy and pasting
Code:
# transaction posting on available balance
import PyHtmlTable
import twodarr
import string,re
import copy
import sys
posting_trans = [] #creating a list of posting debits here
avail_bal = int(input('What is the balance available to pay transactions?')) #getting the starting balance
while True: #building up the list of transactions
ans = input('Please enter the debits in order of posting one at a time. If there is no more, please enter 0:')
if int(ans) == 0:
break
if ans > 0: # to get out of loop
posting_trans.append(ans)
num_trans = int(len(posting_trans)) #counting the number of transactions
print "<b> Beginning available balance of",avail_bal," </b> " # start of the html table
tabledict = {'width':'400','border':2,'bgcolor':'white'}
t = PyHtmlTable.PyHtmlTable( 2, 1 , tabledict )
t.setCellcontents(0,0,"Transactions") #header cells
t.setCellcontents(1,0,"Available Balance")
while True: #trying to create the rest of a dynamic table
if countdown == 0:
break
for countdown in range(1,num_trans):
t.add_row(1)
def newer_bal():
newer_bal(avail_bal - posting_trans[countdown])
t.setCellcontents(0, 1, posting_trans[countdown])
t.setCellcontents(1, 1, newer_bal)
t.display()
Something like that?
# transaction posting on available balance
import PyHtmlTable
posting_trans = [] #creating a list of posting debits here
#getting the starting balance
print 'What is the balance available to pay transactions? '
avail_bal = float(raw_input('Value: '))
while True: #building up the list of transactions
print 'Please enter the debits in order of posting one at a time.'
print 'If there is no more, please enter 0:'
ans = float(raw_input('Value: '))
if ans == 0:
break # to get out of loop
posting_trans.append(ans)
# start of the html table
print "<b> Beginning available balance of %.2f</b>" % avail_bal
tabledict = {'width': '400', 'border': 2, 'bgcolor': 'white'}
t = PyHtmlTable.PyHtmlTable(2, 1, tabledict)
t.setCellcontents(0, 0, "Transaction Value") #header cells
t.setCellcontents(0, 1, "Available Balance")
for line, trans in enumerate(posting_trans):
avail_bal -= trans
t.setCellcontents(line + 1, 0, '%.2f' % trans)
t.setCellcontents(line + 1, 1, '%.2f' % avail_bal)
t.display()
Hints:
Don't use input(). Use raw_input() instead. It has been renamed to input() in python 3.0.
You don't need to store the values in the list. You could store them in the table already, that is the point into using PyHtmlTable. I left the list for didactic purposes.
Read a tutorial. Read documentation. Write lots of code.

Categories