0

I'm currently in the process of producing a quiz as a competition between me and my friends, and to learn a bit more about programming which I am relatively new to. My program is intended to keep the last 3 results for each user that uses the quiz and replaces the oldest result with the newest. The current stage I have reached is being able to check if the user has their name in the file, and if not writes to the file as normal.

    if team == 'Team 1':
        path = 'team1scores.csv'

    elif team == 'Team 2':
        path = 'team2scores.csv'

    elif team == 'Team 3':
        path = 'team3scores.csv'

    else:
        print("--Error Defining File Path--")

with open(path, 'rt') as csvfile:
    ver_read = csv.reader(csvfile, delimiter =",")
    ver_write = csv.writer(csvfile, delimiter =",")
    for row in ver_read:
        if user in row:
            row_data = list(ver_read)
            row_len = len(row_data)
            if row_len >= 3:
            >>> The Problem is here

        else:
            with open(path, 'a+', newline='') as csvfile:
                csvwriter = csv.writer(csvfile, delimiter=',')
                csvwriter.writerows(datacsv)

The problem I have with the program is being able to replace the result, say I had the data below in my csv file with 3 inputs already. These need to be kept in two different columns. As I plan to have a sorting feature included.

Jake,5
Jake,7
Jake,2
Max,9
Lee,8

I have experimented several times with the basis of the code above but I am confused once the program reaches the situation of replacing the information. So far I have been able to overwrite the entire file but not specific pieces of data.

Will the ver_write be neccessary in the next steps?

Edit: I now have an updated version but still have the same problem, This program is adapted from 2ps's answer to fit into my criteria. It still needs to overwrite and needs to print to two different cells for the name and the score. The basis is there for what I need but it won't work.

from collections import OrderedDict
user_data = OrderedDict()
data_to_write = []
with open(path, 'r+') as csvfile:
    ver_read = csv.reader(csvfile, delimiter =";")
    for x, row in enumerate(ver_read):
        if user == row[0]:
            user_data[x] = row
        else:
            data_to_write.append(row)
    if len(user_data) > 2:
        keys = user_data.keys()[-2:]
        for x in keys:
            data_to_write.append(user_data[x])
            data_to_write.append(datacsv)
            with open(path, 'w') as csvfile:
                ver_write = csv.writer(csvfile, delimiter=",")
                ver_write.writerows(data_to_write)
    else:
        with open(path, 'a+', newline='') as csvfile:
            csvwriter = csv.writer(csvfile, delimiter=',')
            csvwriter.writerows(datacsv) 

Am I doing something fundamentally wrong here?

  • What is you problem? Don't know how to implement your logic or having an exception? Besides, please show the full code and give an example of input and expected output. – chinglun Apr 30 '16 at 16:49
  • Have you considered using the Pandas library? It makes this sort of thing much easier - you can do operations on a dataFrame much quicker. I would also try and store your data in a single file, not three. It's probably better to just have a column identifying team/individual taking the quiz. – flyingmeatball Apr 30 '16 at 16:56
  • Does the order of the `John, 4` rows matter (that is, is it okay to have all John's scores grouped)? – Nander Speerstra May 02 '16 at 09:43
  • @NanderSpeerstra As long as the data goes back in the file and the oldest/top data for the user is overwritten it doesn't matter. – Jake Kalcher May 02 '16 at 09:44

3 Answers3

1

As far as I know, you cannot change one row in a file. So you'll have to rewrite the complete file.

I do not know how you insert new data, but you could do the following:

import csv

# Assuming new score
new_score = ['Jake', '3']

# Open the file containing the scores
with open('scores.csv', 'r') as csvfile:
    ver_read = csv.reader(csvfile, delimiter=',')

    # Make a dict that will contain the scores per person        
    names = {}
    for row in ver_read:
        # Grab the name and the score
        name,score = list(row)

        # If it's not in names yet, put it in and make it a list
        if name not in names:
            names[name] = []

        # Append the score to the name list
        names[name].append(score)

# Add the new score
names[new_score[0]].append(new_score[1])

with open('scores.csv', 'w') as csvfile:
    # Loop the names in the names dict
    for name in names:

        # If the person has more than 3 scores, only take the last 3
        if len(names[name]) > 3:
            names[name] = names[name][-3:]

        # For each score, print it
        for score in names[name]:
            print('{},{}'.format(name, score))
            #ver_write.writerow([name, score])

In:

Jake,5
Jake,7
Jake,2
Max,9
Lee,8

New score:

Jake,3

Out:

Jake,7
Jake,2
Jake,3
Max,9
Lee,8
Community
  • 1
  • 1
Nander Speerstra
  • 1,496
  • 6
  • 24
  • 29
0

You could try something like this maybe:

data_to_write = []
with open(path, 'r+') as csvfile:  # read-write mode for file
    ver_read = csv.reader(csvfile, delimiter =",")
    row_data = list(ver_read)

    for row in row_data:
        if user in row:
            if row_data.index(row) >= 3:    # if we found the user in a row after 3
                row = []    # change the information here to whatever suits you
            else:
                row = []    # or here depending on your logic
        data_to_write.append(row)   # store it for afterwards

    # finally write the changes to file
    ver_write = csv.writer(csvfile, delimiter=",")
    ver_write.writerows(data_to_write)
mkaran
  • 2,528
  • 20
  • 23
0
from collections import OrderedDict
user_data = OrderedDict() # dict to hold all matching rows for the user, keyed off of line number
data_to_write = []
with open(path, 'r') as csvfile:  # read-write mode for file
    ver_read = csv.reader(csvfile, delimiter =",")
    for x, row in enumerate(ver_read):
        if user == row[0]:
            user_data[x] = row
        else:
            data_to_write.append(row)   # store it for afterwards
    if len(user_data) >= 3:
        keys = user_data.keys()[-2:] # Grab the last two scores in the file
        for x in keys:
            data_to_write.append(user_data[x])
        # Write the contents of the new score here:
        data_to_write.append(. . . . .)
with open(path, 'w') as csvfile:
    # finally write the changes to file
    ver_write = csv.writer(csvfile, delimiter=",")
    ver_write.writerows(data_to_write)
2ps
  • 15,099
  • 2
  • 27
  • 47
  • I have run into a problem, The name and score cells have merged into one cell. Any solutions? – Jake Kalcher May 01 '16 at 09:09
  • Also the data is not being overwritten and is leaving me with one cell gaps between my results instead. – Jake Kalcher May 01 '16 at 09:54
  • It appears that the user_data is not working somewhere in the code. Any ideas? – Jake Kalcher May 01 '16 at 13:44
  • I have inserted the answer into my program but it is has the problems - shown in previous - comments. I'm hazarding a guess that there is an issue with the user_data somewhere? – Jake Kalcher May 02 '16 at 07:49
  • Yeah, I think I may have messed up the write delimiter. The delimiter on the output CSV should match the delimiter on the input CSV. (either both commas, or both semicolons. Sorry about that! – 2ps May 02 '16 at 22:05