4
\$\begingroup\$

This code is part of a larger code that generates an Arithmetic Quiz, although the code I have show below just saves the score that the user got on the test and their name. When saving the code it checks if the user has taken the quiz before. If the user has taken the quiz before it saves it as 'Older Score' or 'Oldest Score', however if the user has not taken the quiz before it generates a new row for them. Additionally it works out the average score and highest score for all users it has the data for. For my task I'm supposed to make the code as short as possible.

name = ""+first_name+" "+last_name
rows_data = []
class_file_names = ['Class 1.csv', 'Class 2.csv', 'Class 3.csv']
scan = open(class_file_names[int(math_class)-1], 'r+')
rows = csv.reader(scan)
for row in rows:
    rows_data.append(row)
scan.close()
class_file_names=['Class 1.csv', 'Class 2.csv', 'Class 3.csv']
csvfile=open(class_file_names[int(math_class)-1], 'w', newline="")
fieldnames = ['Student Name', 'Oldest Score', 'Older Score', 'Latest Score', 'Average', 'Highest']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
nameFound=False
for x in rows_data[1:]:
    if x[0] == name:
        x[3]=x[2]
        x[2]=x[1]
        x[1]=str(score)
        x[4]=(int(x[1])+int(x[2])+int(x[3]))/3
        x[5]=max(x[1],x[2],x[3])
        nameFound=True
    writer.writerow({'Student Name': x[0], 'Oldest Score': x[3], 'Older Score': x[2], 'Latest Score': x[1], 'Average': x[4], 'Highest' : x[5]})

if nameFound==False:
    writer.writerow({'Student Name': name, 'Latest Score': score, 'Older Score': '0', 'Oldest Score': '0', 'Average': score, 'Highest': score})
csvfile.close()
input("Test complete! Press anything to close.")
\$\endgroup\$
0

1 Answer 1

2
\$\begingroup\$

I'd recommend a few things:

But I'll show how they can make your code nicer.

Using str.format you can easily create name. Alternately, if you don't want to use str.join:

name = '{} {}'.format(first_name, last_name)
name = ' '.join([first_name, last_name])

Using a list comprehension you can reduce the amount of code to create the rows_data.

rows_data = [row for row in csv.reader(scan)]

Using with you can remove the file.close calls. This can lead to a very small amount of code to read the rows_data.

with open(class_file_names[int(math_class) - 1], 'r+') as scan:
    rows_data = [row for row in csv.reader(scan)]

I'll touch on PEP8, class_file_names should be all caps, so CLASS_FILE_NAMES as it's a constant. You should also have a space either side of most operators, the largest exception are commas.

Finally slices makes your x code much easier to read. To get the first three items in a list you can use list[:3] where for two you can use list[:2]. combining these together you can overwrite your existing scores with ease:

x[:3] = [str(score)] + x[:2]

Also your max code may be wrong as it may use the max from the string representation, not from what the numbers mean. And on the second test, you will average as if there has been three tests, where there has been two.

In all I'd use:

CLASS_FILE_NAMES = ['Class 1.csv', 'Class 2.csv', 'Class 3.csv']
FIELDNAMES = ['Student Name', 'Oldest Score', 'Older Score',
              'Latest Score', 'Average', 'Highest']

file_name = CLASS_FILE_NAMES[int(math_class) - 1]
name = '{} {}'.format(first_name, last_name)
with open(file_name, 'r+') as scan:
    rows_data = [row for row in csv.reader(scan)]

with open(file_name, 'w', newline="") as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames=FIELDNAMES)
    writer.writeheader()
    name_found = False
    for x in rows_data[1:]:
        if x[0] == name:
            x[:3] = [str(score)] + x[:2]
            nums = [int(x) for x in x[:3]]
            x[4] = sum(nums) / 3
            x[5] = max(nums)
            nameFound = True
        writer.writerow({
            'Student Name': x[0],
            'Latest Score': x[1],
            'Older Score': x[2],
            'Oldest Score': x[3],
            'Average': x[4],
            'Highest': x[5]})

    if not name_found:
        writer.writerow({
            'Student Name': name,
            'Latest Score': score,
            'Older Score': '0',
            'Oldest Score': '0',
            'Average': score,
            'Highest': score})

input("Test complete! Press anything to close.")
\$\endgroup\$
2
  • \$\begingroup\$ ty @Joe Wallis . My code looks better now and still work. I'll have to remember to use PEP8 in future projects. \$\endgroup\$ Apr 26, 2016 at 6:46
  • \$\begingroup\$ @VideoAssets it's recommended to always use it, but don't be a hobgoblin if something looks nicer by not following it, don't follow it. Best of luck to future projects! \$\endgroup\$
    – Peilonrayz
    Apr 26, 2016 at 7:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.