Write list to 2 different text files - python

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)

Related

2D Array update actually updates two different arrays? [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 1 year ago.
I'm trying to track how many times a selection was made in a 2D array and how many times it was played in another array (it has to deal with having multiple mp3's in a directory). Not even sure I'm describing it well, but hopefully my example will show my issue.
If you take the code below (and don't have the "PlayHistory.csv" file created), run it, type "A1" you will see two 2D arrays print out. Specifically look at entries for "A1". The Selection Count is 0 and Allowed Selection Count is 1. This is what I'd expect. Now, close the program (or IDE in my case) the "PlayHistory.csv" file is present and notice A1 entry is 0). Run the program again and use "A1" as your input and you'll see both the Selection Count is 1 and the Allowed Selection Count is 1. I'm not even updating the SelectionCount array in the attached code. How is this happening?
#!/usr/bin/env python3
#
import os, sys, csv, vlc, time, serial
from pynput.keyboard import Key, Listener
#
USBDrive = None
Action = None
Playlist = []
SelectionCount = []
AllowedCount = []
Sel_char = None
Queue_counter = 0
Play_counter = 0
PlayHistory="PlayHistory.csv"
#
# Create/Find/Open PlayHistory.csv
# Create media folders as needed if new PlayHistory file is created
#
USBDrive = os.path.join("/media/pi", "USB30FD")
if os.path.isfile(os.path.join(USBDrive, PlayHistory)):
datafile = open(os.path.join(USBDrive, PlayHistory), 'r+')
datareader = csv.reader(datafile, delimiter=',')
for row in datareader:
SelectionCount.append(row)
AllowedCount.append(row)
else:
datafile = open(os.path.join(USBDrive, PlayHistory), 'w+')
datawriter = csv.writer(datafile, delimiter=',')
datawriter.writerow(['Selection', 'Count'])
SelectionCount.append(['Selection', 'Count'])
AllowedCount.append(['Selection', 'Count'])
for x in range (65, 87):
if x == 73 or x == 79:
continue
for y in range (1,11):
if y == 10:
datawriter.writerow([chr(x) + str(0),0])
SelectionCount.append([chr(x) + str(0),0])
AllowedCount.append([chr(x) + str(0),0])
# if not os.path.isdir(os.path.join(USBDrive, chr(x) + str(0))):
# os.makedirs(os.path.join(USBDrive, chr(x) + str(0)))
else:
datawriter.writerow([chr(x) + str(y),0])
SelectionCount.append([chr(x) + str(y),0])
AllowedCount.append([chr(x) + str(y),0])
# if not os.path.isdir(os.path.join(USBDrive, chr(x) + str(y))):
# os.makedirs(os.path.join(USBDrive, chr(x) + str(y)))
datafile.flush()
datafile.close()
#AllowedCount == SelectionCount
#
# Find location of Selection in SelectionCount 2D array
#
def find(l, elem):
for row, i in enumerate(l):
try:
column = i.index(elem)
except ValueError:
continue
return row, column
return -1
#
# MediaPlayer function
#
def QueueTracker(tracker, selection):
global Queue_counter, Play_counter
if tracker == "Queue":
Queue_counter = Queue_counter + 1
elif tracker == "Play":
print("Play Counter")
Play_counter = Play_counter + 1
count1,count2=find(SelectionCount, selection)
#SelectionCount[count1][1] = int(SelectionCount[count1][1]) + 1
print("SelectionCount: " + str(SelectionCount[count1][1]))
elif tracker == "Allowed":
print("Allowed Counter")
acount1,acount2=find(AllowedCount, selection)
print(AllowedCount[acount1][1])
AllowedCount[acount1][1] = int(AllowedCount[acount1][1]) + 1
print("AllowedSelectionCount: " + str(AllowedCount[acount1][1]))
print("Selected Count")
print(SelectionCount)
print("Allowed Selection Count")
print(AllowedCount)
#
# Define keyboard actions
#
def on_press(key):
global Action
try:
Sel_char = int(key.char)
except:
try:
Sel_char = str(key.char)
Sel_char = Sel_char.upper()
except:
Sel_char = None
if Sel_char == "Z":
return False
elif Sel_char == "Y":
print("Play Track")
QueueTracker("Played", "A1")
elif type(Sel_char) == str:
Action = Sel_char
elif type(Sel_char) == int:
Action = Action + str(Sel_char)
QueueTracker("Allowed", "A1")
else:
pass
# Read keyboard input
#
print("Ready...")
with Listener(on_press=on_press) as listener:
listener.join()
#
# Program is shutting down
#
print ("")
print ("Writing Play Counts to PlayHistory file")
datafile = open(os.path.join(USBDrive, PlayHistory), 'w+')
datawriter = csv.writer(datafile, delimiter=',')
datawriter.writerows(SelectionCount)
datafile.flush()
datafile.close()
print ("")
print ("Have a nice day!")
print ("")
sys.exit()
Any help would be greatly appreciated.
Thanks! Brian
Your assessment was essentially correct:
for row in datareader:
SelectionCount.append(row)
AllowedCount.append(row)
That does not make two copies. That makes two pointers to one list. If you modify the list in SelectionCount[0], that will also modify AllowedCount[0]. Change that to
for row in datareader:
SelectionCount.append(row)
AllowedCount.append(row[:])
You might also consider this simplification to your first loop creating the CSV data:
for x in 'ABCDEFGHJKLMNPQRSTUV':
for y in range (10):
datawriter.writerow([x + str(y),0])
SelectionCount.append([x + str(y),0])
AllowedCount.append([x + str(y),0])

How can I make it where it will print the longest name/string that was inputed by the user

def myNames():
names = []
while True:
a = input("Enter Name: ")
if a != "done":
names.append(a)
elif a == "done":
return names
def all_lengths(myNames):
num_of_strings = len(myNames)
total_size = 0
for item in myNames:
total_size += len(item)
ave_size = float(total_size) / float(num_of_strings)
print(ave_size)
all_lengths(myNames())
def longestWord(myNames):
count = 0
for i in myNames:
if len(i) > count:
count = len(i)
word = I
print ("the longest string is ", word)
how can I make it print the longest name that was inputted by the user for example: out of Samantha and John it would say that Samantha was the longest name
longestName = ""
for name in myNames:
if len(name) > len(longestName):
longestName = name
print("The longest name is", longestName)
This will check the length of each username, and if the name of that username is longer than the current longest username, it will replace it.
You already have the function for it.
Just need to call the function longestWord().
Write longestWord(myNames()) at the end of the program. Right after,
def longestWord(myNames):
count = 0
for i in myNames:
if len(i) > count:
count = len(i)
word = i # Need to type I in lower case
print ("the longest string is ", word)
Update: Since, you don't want the function to ask for names again, you can move the function calling longestWord()inside the above function where it calculates average, with the parameter as myNames i.e.
def myNames():
names = []
while True:
a = input("Enter Name: ")
if a != "done":
names.append(a)
elif a == "done":
return names
def longestWord(myNames):
count = 0
for i in myNames:
if len(i) > count:
count = len(i)
word = i
print ("the longest string is ", word)
def all_lengths(myNames):
num_of_strings = len(myNames)
total_size = 0
for item in myNames:
total_size += len(item)
ave_size = float(total_size) / float(num_of_strings)
print(ave_size)
longestWord(myNames) # Calling the function with already given names
all_lengths(myNames())

update value in python dictionary by adding a number

I want to make a program that adds a name in the dictionary if it doesn't exist already and count the times it is given as input. My code works, however, it doesn't add 1 when it iterates.
namelist = {}
def namen():
while True:
word = input('Vul een naam in: ')
if word == '':
break
else:
for name in namelist:
if word == name:
namelist[word] += 1
# else wasn't properly indented earlier
else:
namelist[word] = 1
print(namen())
print(namelist)
You can use the dict.get method instead to provide a default value to a new entry to the dict:
namelist = {}
def namen():
while True:
word = input('Vul een naam in: ')
if word == '':
break
else:
for name in namelist:
if word == name:
namelist[word] = namelist.get(word, 0) + 1
Your check is incorrect, you need if rather than for to see if the key exists, then you can remove the inner if statement
if name in namelist:
namelist[word] += 1
else:
namelist[word] = 1
No one said anything about the has_key method of dictionaries, which is in my opinion the standard way to to this:
namelist = {}
def namen():
while True:
word = input('Vul een naam in: ')
if word == '':
break
else:
if namelist.has_key(word):
namelist[word] += 1
else:
namelist[word] = 1
print(namen())
print(namelist)
try this
namelist = {}
def namen():
while True:
word = input('Vul een naam in: ')
if word == '':
break
else:
try:
namelist[word] += 1
except:
namelist[word] = 1
print(namen())
print(namelist)

Why is Filename not a db that the shelve module can open?

import random
import sys
import shelve
def get_input_or_quit(prompt, quit="Q"):
prompt += " (Press '{}' to exit) : ".format(quit)
val = input(prompt).strip()
if val.upper() == quit:
sys.exit("Goodbye")
return val
def prompt_bool(prompt):
while True:
val = get_input_or_quit(prompt).lower()
if val == 'yes':
return True
elif val == 'no':
return False
else:
print ("Invalid input '{}', please try again".format(val))
def prompt_int_small(prompt='', choices=(1,2)):
while True:
val = get_input_or_quit(prompt)
try:
val = int(val)
if choices and val not in choices:
raise ValueError("{} is not in {}".format(val, choices))
return val
except (TypeError, ValueError) as e:
print(
"Not a valid number ({}), please try again".format(e)
)
def prompt_int_big(prompt='', choices=(1,2,3)):
while True:
val = get_input_or_quit(prompt)
try:
val = int(val)
if choices and val not in choices:
raise ValueError("{} is not in {}".format(val, choices))
return val
except (TypeError, ValueError) as e:
print(
"Not a valid number ({}), please try again".format(e)
)
role = prompt_int_small("Are you a teacher or student? Press 1 if you are a student or 2 if you are a teacher")
if role == 1:
score=0
name=input("What is your name?")
print ("Alright",name,"welcome to your maths quiz."
" Remember to round all answers to 5 decimal places.")
level_of_difficulty = prompt_int_big("What level of difficulty are you working at?\n"
"Press 1 for low, 2 for intermediate "
"or 3 for high\n")
if level_of_difficulty == 3:
ops = ['+', '-', '*', '/']
else:
ops = ['+', '-', '*']
for question_num in range(1, 11):
if level_of_difficulty == 1:
max_number = 10
else:
max_number = 20
number_1 = random.randrange(1, max_number)
number_2 = random.randrange(1, max_number)
operation = random.choice(ops)
maths = round(eval(str(number_1) + operation + str(number_2)),5)
print('\nQuestion number: {}'.format(question_num))
print ("The question is",number_1,operation,number_2)
answer = float(input("What is your answer: "))
if answer == maths:
print("Correct")
score = score + 1
else:
print ("Incorrect. The actual answer is",maths)
if score >5:
print("Well done you scored",score,"out of 10")
else:
print("Unfortunately you only scored",score,"out of 10. Better luck next time")
class_number = prompt_int_big("Before your score is saved ,are you in class 1, 2 or 3? Press the matching number")
filename = (str(class_number) + "txt")
with shelve.open(filename) as db: # This is the effected line
old_scores = db.get(name, [])
old_scores.extend(score)
db[name] =score[-3:]
if prompt_bool("Do you wish to view previous results for your class"):
for line in lines:
print (line)
else:
sys.exit("Thanks for taking part in the quiz, your teacher should discuss your score with you later")
if role == 2:
class_number = prompt_int_big("Which class' scores would you like to see? Press 1 for class 1, 2 for class 2 or 3 for class 3")
filename = (str(class_number) + "txt")
sort_or_not = int(input("Would youlike to sort these scores in any way? Press 1 if the answer is no or 2 if the answer is yes"))
if sort_or_not == 1:
f = open(filename, "r")
lines = [line for line in f if line.strip()]
lines.sort()
for line in lines:
print (line)
if sort_or_not == 2:
type_of_sort = int(input("How would you like to sort these scores? Press 1 for scores in alphabetical order with each student's highest score for the tests, 2 if you would like to see the students' highest scores sorted from highest to lowest and 3 if you like to see these student's average scores sorted from highest to lowest"))
if type_of_sort == 1:
with open(filename , 'r') as r:
for line in sorted(r):
print(line, end='')
if type_of_sort == 2:
file = open(filename, 'r')
lines = file.read().splitlines()
s = {lines[i]:[int(k) for k in lines[i+1:i+4]] for i in range(0,len(lines),4)}
for i in sorted(s.keys()):
print (i,max(s[i]))
avg_mark = lambda name:sum(s[name])/len(s[name])
for i in sorted(s.keys(),key=avg_mark,reverse=True):
print (i,avg_mark(i))
if type_of_sort == 3:
file = open(filename, 'r')
lines = file.read().splitlines()
s = {lines[i]:[int(k) for k in lines[i+1:i+4]] for i in range(0,len(lines),4)}
for i in sorted(s.keys()):
print (i,max(s[i]))
high_mark = lambda name:max(s[name])
for i in sorted(s.keys(),key=high_mark,reverse=True):
print (i,high_mark(i))
The shelve module part of my code is not working and I don't understand what the error is trying to say. I am trying to save the last three scores to a students name and then sort it in a variety of ways . The error comes up after the quiz is completed as a student.
Try deleting the file at filename and running the script again, so that the script is responsible for creating the database file in the correct format. If you ask it to open an empty file or a file that was created by some other means (e.g. CSV, JSON, etc.) then it doesn't know how to handle it.

Python dictionary if/else invalid syntax

I cant figure out why line 104 keeps returning invalid syntax, can someone please point me in the right direction? Does it have something to do with the way i used elif? Sorry if this is a newbie question!
Line 104 is the else statement in the for item in workingDict.keys() loops inside printGrammar
import sys
import string
from collections import defaultdict
#default length of 3
stringLength = 3
#get last argument of command line(file)
if len(sys.argv) == 1:
#get a length from user
try:
stringLength = int(input('Length? '))
filename = input('Filename: ')
except ValueError:
print("Not a number")
elif len(sys.argv) == 2:
#get a length from user
try:
stringLength = int(input('Length? '))
filename = sys.argv[1]
except ValueError:
print("Not a number")
elif len(sys.argv) == 3:
filename = sys.argv[2]
stringLength = sys.argv[1].split('l')[1]
else:
print("Invalid input!")
#get start symbol
with open(filename, "r") as grammar:
#read file
lines = grammar.readlines()
start = lines[0].split('=')[0]
start = start.replace(" ", "")
#checks
#print(stringLength)
#print(filename)
#print(start)
def str2dict(filename):
result = defaultdict(list)
with open(filename, "r") as grammar:
#read file
lines = grammar.readlines()
count = 0
#loop through
for line in lines:
#append info
line = line.rstrip()
result[line[0]].append(line.split('=')[1])
return result
workingDict = str2dict("Binary.txt")
print(workingDict)
def printGrammar(result):
sentenceList = []
workList = []
workList.append(start)
i = 0
firstNT = ""
#While the worklist is not empty:
while(len(workList) != 0):
#Get and delete one potential sentence s from the worklist.
symbol = workList.pop()
#If the | s | > N, continue.
if len(str(symbol).replace(" ", "")) > int(stringLength):
continue
else:
if str(symbol) in workingDict.keys():
#append the right derivation
for item in workingDict.get(symbol):
workList.append(list(item.replace(" ", "")))
#workList.append(str(workingDict.get(symbol)))
#add derivation
print(workingDict.keys())
#If s has no nonterminals, print s and continue.
for item in workingDict.keys():
print("test")
print(''.join(item))
if len(item) != 1:
continue
#if the element is in dictionary, dont print
elif ''.join(item) in workingDict.keys():
continue
print(symbol)
#if element is not in dictionary, print
else:
print("THIS IS A TERMINAL!!")
print(item)
#Choose the leftmost nonterminal NT.
print(workList)
#For all productions NT -> rhs:
#Replace NT in s with rhs; call it tmp.
#Store tmp on worklist.
return workList
print (printGrammar(workingDict))
You need to indent the line
print(symbol)
to the same level as continue.

Categories