Currently, I have a CSV file set out like this:
Element,Weight
"Hydrogen","1"
"Oxygen","16"
Eventually it'll have all of the elements and their atomic weights next to them, but putting all of that in is rather pointless unless I get this issue solved first.
The main Python program is as follows:
import csv
reader = csv.reader(open("chem.csv", "rb"))
first = raw_input("Enter first element: ")
second = raw_input("Enter second element: ")
if first == "Hydrogen" or "hydrogen":
for Weight in reader:
print Weight
else:
print "No."
Now, as you might be able to tell from that, my aim here is to have the program display the weight of hydrogen as taken from the CSV file, for now. However, currently it just ends up displaying the following:
Enter first element: hydrogen
Enter second element: oxygen
['Element', 'Weight']
['Hydrogen', '1']
['Oxygen', '16']
So, basically, how can I make it so that it goes to the Hydrogen row and then takes the weight value from the second column? I should be able to go from there to nail the rest of the program, but this part has got me stuck.
As a secondary thing, is it at all possible to have it so that I won't have to have what is essentially a list of elements in the main Python program as well as in the CSV file? It'd cut down a lot on the clutter, but I just can't get it figured out.
Instead of iterating over the data it is probably nicer to store it in an easy accessible way, e.g. a dictionary mapping name to weight. Then you can just do a look-up for the entered string and display the result (or not if there is none).
import csv
#Read in data anbd store it in dictionary.
#The element name will be stored in lowercase.
elemen_data = { element.lower():int(weight) for element,weight in csv.reader(open("in", "rb"))}
first = raw_input("Enter first element: ")
second = raw_input("Enter second element: ")
#Look for the weight of the entered element (after converting it to all lowercase)
weight_first = elemen_data.get(first.lower())
weight_second = elemen_data.get(second.lower())
if weight_first is not None:
print 'First Element:', first, 'Weight:', weight_first
else:
print 'First Element', first, 'not found'
if weight_second is not None:
print 'Second Element:', second, 'Weight:', weight_first
else:
print 'Second Element', second, 'not found'
Storing your data apart from you program logic can make sense if you want to be able to easily make changes to the data without touching the program. So having a csv-file that is read in is absolutely okay. (As long as the data has a reasonable size)
The problem is that when you iterate over csv.reader object you receive csv file rows as lists of your row cells values. So you can try next for your case:
if first in ("Hydrogen", "hydrogen"):
for Weight in reader:
if Weight[0] == first:
print Weight[1]
That's not the best code, but that returns the value you wanted.
First problem:
if first == "Hydrogen" or "hydrogen":
That won't return what you want. You either want:
if first == 'Hydrogen' or first == 'hydrogen':
or
if first in ['Hydrogen', 'hydrogen']:
Or better yet:
if first.lower() == 'hydrogen'
Which would work for all capitalizations, like HYDrogen.
Then, in that you can do what you want:
for row in reader:
if row[0].lower() == first.lower():
print row[1]
Of course, this could be cleaned up a bit by using a dictionary of values; you probably don't want an if statement for every element, but there you go.
Related
I'm writing a code as a "checklist" for something that is to be made.
each line is basically:
a0=int(input(f'do step one, then enter 1 to cont')
a1=int(input(f'do step two, then enter 1 to cont')
So, how can I skip to line a4 (or a(n) ) and continue from there?
My thoughts were to define each line and store each variable in a list. Then use a while loop to start from wherever. I just can't figure out how to eh, this is where I lose it. I guess I'm trying to convert the string to a variable name, to define it from there. See below:
ail=len(ai) #where ai=[a0,a1,a2..]
a=0 #i would input a as any val.
while a in range (0,ail):
b=(f'a{a}') #this line would determine the "instruction line" to start from.
exec("%s = %d" % (b,b)) #this is the line that names a var from a string
b0=int(input(f'{b}'))
I suggest you use dictionary instead of list. you can access the elements of dictionary using keys and that is going to help you pick a specific spot to traverse from.
Dictionary keys
I create a dictionary from a dataset and now I want to access every single row of the dictionary. Every single row of this dictionary contains 2 names, ex: Winner: Alex Loser: Leo.
My problem is that I don't know how to access the 2 names by index.
I would like something like this:
Row 1: Winner: Alex
Loser: Leo
and I would like to access the row like this: dictionary[x] -> so I can get the row and then once I have the row I want to access it like a=raw[y] and b=raw[y+1]. And then I want to print A and B. I want to do this because I have to copy just one specific player from every single row and to save it into another dictionary.
This is the code that I wrote to create the dictionary and to access it but doesn't work as I want.
dicti= imd4.to_dict('index') // dicti is the dictionary that I created and imd4 is the dataset containing the Winner and the Loser name
for x in dicti:
print (x,':')
for y in dicti[x]:
a=dicti[x][y]
b=dicti[x][y+1] //I can't do this but I would like to do it. So I can save the data base on their index
print (y,':',dicti[x][y])
print('Test :' ,a)
Here you can see how the dataset is build
Thank you in advance for your help.
Let's set up a test dictionary:
test_dictionary=[
{'winner':'ross','loser:'chandler'},
{'winner':'rachael','loser:'phoebe'},
{'winner':'joey','loser:'monica'},
{'winner':'gunther','loser:'chandler'}
]
We can loop through this easily:
for contest in test_dictionary:
print (contest)
and we could add a line number using the enumerate function:
for line_number, contect in test_dictionary:
print (line_number,contest)
so now we have the line number we can easily access the next element - we have to bear in mind though we don't want to access the final element as we can't print the contest after this so we loop to the [-1] element:
for line_number, contect in test_dictionary[:-1]:
print (line_number,contest)
print (line_number+1,test_dictionary[line_number+1])
We could also simply use a range on the length of test_dictionary and access the elements directly:
for line_number in range(len(test_dictionary)-1]:
print (line_number,test_dictionary[line_number])
print (line_number+1,test_dictionary[line_number+1])
I am trying to make a program where my students will enter their ID numbers so I can (later in the code) automate sending attendance, and record who has handed in homework and who hasn't so emails can be sent to parents. I have everything else made, but I cannot get the inputting of student ID's working.
What I am trying to do:
1)make sure that their input is 7 characters long
2)check their ID exists in 'fakeID'
2a)have the students confirm their name from 'classNames' with a y/n.
2b) append their name into inputIDList
3) if the input is == to 9999990 exit the loop.
What it is doing:
1) asking for input
2) moving on in the code and not looping
3) not appending inputIDList
I think I am making this too complicated for my current skill level.
edit:
The loop is not checking to see if the inputed ID is in my fakeID list.
Also, it isnt looping for, so once the input is entered it continues on with the next set of code.
edit2:
updated code that works. :D
fakeID = ['1111111','1111112','1111113','1111114','1111115']
classNames = ['name1', 'name2', 'name3', 'name4', 'name5']
toplist = list(zip(fakeID, classNames))
inputIDList =[]
def inputID():
while True:
id = input('Please enter your student ID and hit Enter')
if id == '9999990':
print('Done')
break
if id in fakeID:
inputIDList.append(id)
print('recorder')
continue
if id not in fakeID:
print('I do not know this ID. Please try again.')
continue
If I understood your problem correctly then I suppose that you are trying to save the ID numbers of the students in inputIdList and then check whether a particular ID is in inputIdList or not. In the last if condition you are trying to compare a List type object with a String type object which will definitely throw an TypeError. Instead define the following function and call it in the if condition.
def check_list(id):
try:
inputIdList.index(id)
return True
except TypeError:
return False
list.index() method tries to find the element in the list and returns the index number of the element. And then call this function in your if condition.
if check_list('9999990'):
print('done')
#break
Furthermore there is no need to assign inputIdList = [""] if you have already intialized it to inputIdList = [].
If the problem persists please send the output in the thread.
Here is something to get you started:
fakeID = {'1111111','1111112','1111113','1111114','1111115'}
while True:
id = input('Please enter your student ID and hit Enter')
if id == '9999990':
print('Done')
break
if id not in fakeID:
print('I do not know this ID. Please try again.')
continue
as Abarnert said you need to restructure your method. but I think I found where you were stuck.
after you have checked for the length of input number, you should check whether that number matches any fakeID,and get the corresponding class name.
so your first loop should be like this
for i in toplist:
rather than
for i in [i for i,x in enumerate(inputIDList) if x == fakeID]:
since inputIDList is empty your program will not go inside the loop. And inside the changed loop you should be checking
if s == fakeID
This is the limit of what I could understand of your desired operation. But if you need further help just ask.
cheers.
I'm attempting to write a script that makes a sorted list out of items stored in this format:
&&
TASK:
PROJECT:
CONTEXT:
DUE_DATE:
COMPLETION_DATE:
PRIORITY:
%%
I have a pretty good idea of the logic behind what I'm trying to do, but I'm very new to Python so I'm struggling with the implementation. Here's what I have so far:
import sys
import getopt
#add function
if sys.argv[1] == 'add':
try:
f = open("todo.txt", "added")
try:
f.write("TASK:" + sys.argv[2] + "\n")
project = raw_input("Please enter the project: ")
f.write("PROJECT:" + project + "\n")
context = raw_input("Please enter the context: ")
f.write("CONTEXT:" + context + "\n")
duedate = raw_input("Please enter the due date: ")
f.write("DUE_DATE:" + duedate + "\n")
completiondate = raw_input("Please enter the completion date: ")
f.write("COMPLETEION_DATE:" + completiondate + "\n")
priority = raw_input("Please enter the priority level")
f.write("PRIORITY:" + priority + "\n")
finally:
f.close()
except IOError:
pass
#list function
if sys.argv[1] == 'list':
listnum = 1
try:
with open("todo.txt", "r") as f:
searchlines = f.readlines()
for i, line in enumerate(searchlines):
if "TASK:" in line:
for l in searchlines[i:i+3]:
print listnum, l[5:],
listnum += listnum
except IOError:
pass
#complete function
if sys.argv[1] == 'complete':
listName.pop(args[0]-1);#this pops it out and deletes it. need to sort into order and from that list. delete that item
#by popping and it will be the -1 of the one from the list.
Now, my add function works fine. I understand that argeparse(sp?) would let me add all of the meta data with a single line, but I figured I'd keep it as simple as possible. My list function at the moment simply lists all of the items based on their order within the file, but it doesn't have any sort of filter functionality. It also doesn't display the meta data below TASK: lines.
What I want to do with my list function is to have the default action sort all items in the text file based on priority. I'd like to accept additional search "tags" in the same line, and have the list function generate a list of TASKS: who have any number of meta data that match any of the search tags, and I want the filtered list to also be sorted based on priority.
What I'm thinking is to use letter tags for priority (A, B, etc...) and traversing to each entry in the file. I would then compare the task name and all of the meta data to each filter tag. If a match occurs, I would check the priority, and display the entry if the priority is "A". If the priority is not "A", but a match occurs, I would make some sort of bool flag turn to 1 to let me know the program needs to traverse the list again while looking for the next level of priority.
The things I don't know how to do:
Traverse the list and look for match, then look at the priority.
Display the filtered or unfiltered list with the TASK: lines enumerated and all other lines indented and NOT enumerated.
How to have the program stop traversing the list once all valid list candidates for the particular filter have been displayed
Not let previously displayed entries trigger the bool that causes the program to keep looking for more entries.
If possible, I'd like complete to look for a given task name, and if found, delete the task name and the next 6 lines in the text file.
Thank you for any help you can provide!
Relatively new to programming hence why I've chosen to use python to learn.
At the moment I'm attempting to read a list of Usernames, passwords from an Excel Spreadsheet with XLRD and use them to login to something. Then back out and go to the next line. Log in etc and keep going.
Here is a snippit of the code:
import xlrd
wb = xlrd.open_workbook('test_spreadsheet.xls')
# Load XLRD Excel Reader
sheetname = wb.sheet_names() #Read for XCL Sheet names
sh1 = wb.sheet_by_index(0) #Login
def readRows():
for rownum in range(sh1.nrows):
rows = sh1.row_values(rownum)
userNm = rows[4]
Password = rows[5]
supID = rows[6]
print userNm, Password, supID
print readRows()
I've gotten the variables out and it reads all of them in one shot, here is where my lack of programming skills come in to play. I know I need to iterate through these and do something with them but Im kind of lost on what is the best practice. Any insight would be great.
Thank you again
couple of pointers:
i'd suggest you not print your function with no return value, instead just call it, or return something to print.
def readRows():
for rownum in range(sh1.nrows):
rows = sh1.row_values(rownum)
userNm = rows[4]
Password = rows[5]
supID = rows[6]
print userNm, Password, supID
readRows()
or looking at the docs you can take a slice from the row_values:
row_values(rowx, start_colx=0,
end_colx=None) [#]
Returns a slice of the values of the cells in the given row.
because you just want rows with index 4 - 6:
def readRows():
# using list comprehension
return [ sh1.row_values(idx, 4, 6) for idx in range(sh1.nrows) ]
print readRows()
using the second method you get a list return value from your function, you can use this function to set a variable with all of your data you read from the excel file. The list is actually a list of lists containing your row values.
L1 = readRows()
for row in L1:
print row[0], row[1], row[2]
After you have your data, you are able to manipulate it by iterating through the list, much like for the print example above.
def login(name, password, id):
# do stuff with name password and id passed into method
...
for row in L1:
login(row)
you may also want to look into different data structures for storing your data. If you need to find a user by name using a dictionary is probably your best bet:
def readRows():
rows = [ sh1.row_values(idx, 4, 6) for idx in range(sh1.nrows) ]
# using list comprehension
return dict([ [row[4], (row[5], row[6])] for row in rows ])
D1 = readRows()
print D['Bob']
('sdfadfadf',23)
import pprint
pprint.pprint(D1)
{'Bob': ('sdafdfadf',23),
'Cat': ('asdfa',24),
'Dog': ('fadfasdf',24)}
one thing to note is that dictionary values returned arbitrarily ordered in python.
I'm not sure if you are intent on using xlrd, but you may want to check out PyWorkbooks (note, I am the writter of PyWorkbooks :D)
from PyWorkbooks.ExWorkbook import ExWorkbook
B = ExWorkbook()
B.change_sheet(0)
# Note: it might be B[:1000, 3:6]. I can't remember if xlrd uses pythonic addressing (0 is first row)
data = B[:1000,4:7] # gets a generator, the '1000' is arbitrarily large.
def readRows()
while True:
try:
userNm, Password, supID = data.next() # you could also do data[0]
print userNm, Password, supID
if usrNm == None: break # when there is no more data it stops
except IndexError:
print 'list too long'
readRows()
You will find that this is significantly faster (and easier I hope) than anything you would have done. Your method will get an entire row, which could be a thousand elements long. I have written this to retrieve data as fast as possible (and included support for such things as numpy).
In your case, speed probably isn't as important. But in the future, it might be :D
Check it out. Documentation is available with the program for newbie users.
http://sourceforge.net/projects/pyworkbooks/
Seems to be good. With one remark: you should replace "rows" by "cells" because you actually read values from cells in every single row