0

I'm trying to create a leaderboard in python, where a player will get a score from playing a game, which will write to a .csv file. I then need to read from this leaderboard, sorted from largest at the top to smallest at the bottom. Is the sorting something that should be done when the values are written to the file, when i read the file, or somewhere in between?

my code:

writefile=open("leaderboard.csv","a")
writefile.write(name+", "points)
writefile.close()

readfile=open("leaderboard.csv","r")

I'm hoping to display the top 5 scores and the accompanying names. It is this point that I have hit a brick wall. Thanks for any help.

Edit: getting the error 'list index out of range'

import csv

name = 'Test'
score = 3

with open('scores.csv', 'a') as f:
    writer = csv.writer(f)
    writer.writerow([name, score])

with open('scores.csv') as f:
    reader = csv.reader(f)
    scores = sorted(reader, key=lambda row: (float(row[1]), row[0]))
    top5 = scores[-5:]

csv file:

test1   3

test2   3

test3   3
Matt Oram
  • 5
  • 4
  • Can you show us first 5 lines of your csv file? – Matina G Nov 22 '18 at 14:08
  • Why don't you just serialize the scoreboard with pickle? What's the point of `.csv` file, if you both write/read in python code? – Denis Nov 22 '18 at 14:10
  • @MatinaG John 9 Matt 6 test1 0 Mike 3 Hi! 6 I understand this is hard to read as plain text – Matt Oram Nov 22 '18 at 14:11
  • @user3051029 long story, it's part of the criteria :( – Matt Oram Nov 22 '18 at 14:13
  • Comma separated? – Matina G Nov 22 '18 at 14:14
  • @MatinaG i copied that from excel, so the commas aren't there (as excel replaces the comma with a new column) but yes, when I save to the file they are comma separated. Edit: Realised I typed my code wrong above, there should be a + between the "," and 'points' – Matt Oram Nov 22 '18 at 14:15
  • How are your name and points structured in your code? You can sort the points before you write it to your `csv` if it's permissible. – r.ook Nov 22 '18 at 14:27
  • 1
    `name+", "points` is not going to work as you hope if `name` has comma characters in it. You'll want to wrap those in quotation marks or something like that. Better to use the csv module or pandas as in the answers below which will handle all of that for you. – Dan Nov 22 '18 at 15:16
  • Possible duplicate of [sort csv by column](https://stackoverflow.com/questions/2100353/sort-csv-by-column) – mdaniel Nov 22 '18 at 22:48

2 Answers2

2

Python has a csv module in the standard library. It's very simple to use:

import csv

with open('scores.csv', 'a') as f:
    writer = csv.writer(f)
    writer.writerow([name, score])

with open('scores.csv') as f:
    reader = csv.reader(f)
    scores = sorted(reader, key=lambda row: (float(row[1]), row[0]))
    top5 = scores[-5:]

Is the sorting something that should be done when the values are written to the file, when i read the file, or somewhere in between?

Both approaches have their benefits. If you sort when you read, you can simply append to the file, which makes writing new scores faster. You do take more time when reading as you have to sort it before you can figure out the highest score, but in a local leaderboard file this is unlikely to be a problem as you are unlikely to have more than a few thousands of lines, so you'll likely be fine with sorting when reading.

If you sort while writing, this comes with the problem that you'll have to rewrite the entire file every time a new score is added. However, it's also easier to cleanup the leaderboard file if you sort while writing. You can simply remove old/low scores that you don't care about anymore while writing.

Lie Ryan
  • 62,238
  • 13
  • 100
  • 144
  • +2 because for using the csv module. CSV does not mean to just join your values with the separator without caring for escapes, line breaks or whatever comes along. If the file is larger than a few lines and you plan to have more files lying around, wrap that easily with the `gzip` module and you'll save a lot of disk space. – Risadinha Nov 22 '18 at 14:48
  • Hi, i got this error message: scores = sorted(reader, key=lambda row: (row[1], row[0])) IndexError: list index out of range – Matt Oram Nov 22 '18 at 14:59
  • @MattOram: your input file contains an error most likely, or it may have used a different csv dialect (the csv module can be configured for different dialects). If you used my code to both write and read the CSV though, you shouldn't havea problem . Also, note there's a little unrelated errata on that line as the score should be sorted as numeric value instead of as a string. – Lie Ryan Nov 22 '18 at 15:11
  • @LieRyan can't find an error? It is saving to the file just fine, but trips up at the scores = sorted line. – Matt Oram Nov 23 '18 at 08:43
  • @LieRyan update: got it to print the 5 lowest scores...? Edit: Not even the 5 lowest, just 5 random values. – Matt Oram Nov 23 '18 at 09:25
  • @MattOram: the code in my answer works perfectly fine, it saves, read, and sorts the top 5 as I expected. You should post your [MCVE](https://stackoverflow.com/help/mcve) code, otherwise there's nothing I could do to help as I can't reproduce your issue otherwise. – Lie Ryan Nov 23 '18 at 10:52
  • @LieRyanhow shall I post my code? (new here, sorry) Also, it includes lists from a seperate file, shall i move them to my index file? – Matt Oram Nov 23 '18 at 11:00
  • @MattOram: after you've reduced and removed all irrelevant code, run the code to make sure it still executes and still displays the problem, you can edit your original question and add your MCVE there, also include a small sample of other input files you may be using. Make sure that the included sample data demonstrates the problem. – Lie Ryan Nov 23 '18 at 11:11
  • @MattOram You didn't make the MCVE correctly, your code should execute and display the exact problem you're having. Your code is missing import statements and a number of other errors, none of which seems related to what you mentioned. – Lie Ryan Nov 23 '18 at 11:37
  • @MattOram The code you posted still does not demonstrate the problem you're having. You still hadn't included all the things needed to reproduce the problem. – Lie Ryan Nov 23 '18 at 11:45
  • @LieRyan it is all of the code in a new 'test.py' file I created, copied exactly. The problem still occurs. – Matt Oram Nov 23 '18 at 11:48
  • @MattOram: As I mentioned a few comments above: "your input file contains an error". Did you check what's in your scores.csv? – Lie Ryan Nov 23 '18 at 11:49
  • @LieRyan I did, names and scores in columns A and B, seperated by one line each eg. John, 3 Mark, 4 – Matt Oram Nov 23 '18 at 11:52
  • @MattOram Post your csv file – Lie Ryan Nov 23 '18 at 11:54
  • @LieRyan how do I do this? Easier to email it to you? – Matt Oram Nov 23 '18 at 11:58
  • @MattOram No, do the same thing you did with the code. Reduce it until it contains just a few lines that still demonstrates the problem. Then edit the question. – Lie Ryan Nov 23 '18 at 12:00
  • @MattOram: your posted file is not valid per your original question. A comma-separated values (CSV) file is by default separated by commas. Your file uses a different delimiter. Python csv library can read this (despite the name, the module can read any delimited file), as long as you [configure the correct delimiter](https://docs.python.org/3/library/csv.html#csv-fmt-params) when you read/write the file using, or you need to modify/configure whatever program generated your input file to output using the expected delimiter. – Lie Ryan Nov 23 '18 at 12:14
  • @LieRyan thanks for clarifying this. Having never used .csv files inpython before, I don't know what I need to change. I used your code exactly, and so the variables are separated however you coded. Is a comma not the delimiter being used in `([name, score])` ? – Matt Oram Nov 23 '18 at 12:21
1

Try this:

import pandas as pd
df = pd.read_csv('myfullfilepath.csv', sep=',', names=['name', 'score'])
df = df.sort_values(['score'], ascending=False)
first_ten = df.head(10)
first_ten.to_csv('myfullpath.csv', index=False). 

I named the columns like that , following the structure tat you suggested.

Matina G
  • 1,452
  • 2
  • 14
  • 28
  • Getting the error 'No module named pandas', do i need to pip install? – Matt Oram Nov 22 '18 at 14:18
  • 1
    Yes. Note that pandas is a truly usefull module! – Matina G Nov 22 '18 at 14:18
  • Thanks, I'll let you know how it goes – Matt Oram Nov 22 '18 at 14:21
  • 2
    If you don't already have `pandas`, installing it just to sort your `csv` file is somewhat overkill... – r.ook Nov 22 '18 at 14:22
  • Sure. But it seems like he is just starting with python, so he might be needing pandas sooner or later. – Matina G Nov 22 '18 at 14:24
  • It highly depends what they're using python for. `pandas` is mostly for data analysis but if they're using python more script/network/game related might have little use for it. – r.ook Nov 22 '18 at 14:25
  • For completeness, you should add the syntax to write to a csv i.e. `df.to_csv('myfullpath.csv', index=False)`. Also why are you assuming the file is semicolon separated? That sounds more like something specific to your locale. – Dan Nov 22 '18 at 15:11
  • 1
    My bad, I put a semicolon separator by reflex. Fixed it. – Matina G Nov 22 '18 at 16:15