-1

I understand there's different ways of storing data in Python but I can't figure what to use for my needs.

I've made a small client/server game, and I want the amount of guesses it took them to be their score. I would then like to write their name (currently the IP address) along with the score into a file as to create a list of high scores. While I can do that perfectly fine, I only want a maximum of 5 scores stored and to be able to sort them so that when I display the high scores and names to the user, the lowest (being the best score) at the top. I'd also like to allow the username to exist more than once.

While it's easy to write the data and read it, I really can't figure out what data type to use, dictionary would make a lot of sense in some cases, but a key can only have one value and the key can only exist once, a list has no relation to other specific values contained within so neither make sense to use, and tuples can't be sorted either it seems.

I was thinking about reading each line into a sperate list and then using the index to compare the score so I could sort them and write it back to the file, but this would be bad on memory in my opinion?

What would be the easiest method to save the name and score together without using some extreme learning curve like SQL?

PurplProto
  • 143
  • 2
  • 14

2 Answers2

1

A format with a pretty small learning curve would be json.

It's basically a dictionary each key can be a number, string, boolean, float, array, or another dictionary (may have more types).

>>> d = {}
>>> d['someId'] = {'somekey': [0,2,3]}
>>> d
{'someId': {'somekey': [0, 2, 3]}}
>>> d['someId']['somekey']
[0, 2, 3]
>>> d['someId']['number'] = 23456776543
>>> d['someId']['number']
23456776543

Once you get the hang of json consider an ODM / ORM for mongo.

Or for the time being, add a helper function to sort by score pulling in the score and name.

>>> d = {'user1': {'name': 'howdy', 'score': 11},'user2': {'name': 'howdy2', 'score': 12}}
>>> d.keys()
['user2', 'user1']
>>> for user_id in d.keys():
...     print(d[user_id]['name'], d[user_id]['score'])
... 
('howdy2', 12)
('howdy', 11)

If its necessary to setup relational data and models then consider sqlite as it has the basics without being as complicated to setup as postgres or mysql.

Example json reading:

Example json writing:

Community
  • 1
  • 1
jmunsch
  • 22,771
  • 11
  • 93
  • 114
  • I could try this, but there'd be a problem. Since the user's name is the IP it could occur multiple times, thus it cannot be the primary key if you like. I currently have it to write `IP, score`. But I've also come across another problem, you can't write lists to a file, I have to convert them to string first which when you read it, it's still a string of course and converting it back to list will have each char as a value. Would it help if I post my code? – PurplProto Nov 01 '15 at 17:45
  • I was thinking, maybe I could have 5 keys i.e. the numbers 1-5 and use that as the key, so key `1` always contained the top score. But if a new top score was achieved, how would I push it's values down to enter the new top score in key `1` and delete the lowest score so that there was still only the maximum of 5 keys? – PurplProto Nov 01 '15 at 17:57
  • You can write a list to a `json` file, and instead of using the ip as the key, use a unique key to identify a user. Mongo uses a bson object id. If you wanted the unique keys to be the numbers 1-5 thats fine you can do that. To pull out a sorted list you will have to write a helper function that saves the ids for the min and max scores. You could accomplish this with 1 for loop. – jmunsch Nov 01 '15 at 18:50
  • I've made some progress using csv. I can now read and write the values, but I'm have trouble sorting them because it's a list of 2 values within a list. i.e. `mylist.sort()` doesn't work because the values inside `mylist` has the data type of list not str or int like this `mylist = [[score1, ip1], [score2, ip2]]`. Essentially I need to sort `mylist` based on `mylist[n[0]]` with n being the list inside `mylist` if that makes sense? Which I'm not sure is possible without pulling each value out of `mylist` and comparing `n[0]` of each value pulled which is a question completely different to this. – PurplProto Nov 01 '15 at 19:10
  • I just realised this is basically what @Vinay is saying in his answer below. – PurplProto Nov 01 '15 at 19:14
0

You can store a list of tuples with each tuple containing data in a particular order (eg. score, name etc). Then you can sort the list using list.sort() function by defining a function f to compare the scores and passing the function in sort().

Vinay
  • 51
  • 4
  • Could you give an example of how that function would work? – PurplProto Nov 01 '15 at 19:17
  • You can look at it here http://stackoverflow.com/questions/3216398/sorting-by-arbitrary-lambda-in-python . This directly uses lambda function. – Vinay Nov 01 '15 at 19:34
  • Splendid, I'll take a look. Thanks! – PurplProto Nov 01 '15 at 19:47
  • Looks like it doesn't work with lists. Is there anything similar for lists? Since when I read my file it creates a lists within a list by default, I don't think there's a way to read it into tuples within a list? I'm currently using this to read from my file: `with open('Scores.csv', 'r') as scores: reader = csv.reader(scores) tscores = [[str(e) for e in r] for r in reader]` So now `tscores = [[score1, IP1], [score2, IP2]]`. – PurplProto Nov 01 '15 at 20:34
  • Tuples was just an idea.You can directly use it for list of lists and the link above clearly has the way of doing it. – Vinay Nov 01 '15 at 20:37
  • I think I've sort of found the problem. The file's values are being read in as string since `tscores = [[str(e) for e in r] for r in reader]` using `int(e)` causes an error because of the IP address. So I think I need to make the first value an integer. But, since I have it as `tscores.sort(key=lambda x: x[0])` which should sort by the first value, but it's reading the second which is the IP address since that's what's coming up in the error? Why is it reading the second value instead of the first like specified? I've double checked to make sure it's formatted `[[score, IP]]` as well. – PurplProto Nov 01 '15 at 21:10
  • Just to clarify, the error is `TypeError: unorderable types: int() < str()` – PurplProto Nov 01 '15 at 21:11
  • Scrap the second paragraph in the comment before the last. The IP has nothing to do with the current error, that was caused through me trying to fix the current error. So it is because I need the first value to be `int()` rather than `str()` Which means I'll have to iterate through each one some how. – PurplProto Nov 01 '15 at 21:19
  • I managed to change them to `int()` using suggestions in this thread https://stackoverflow.com/questions/9869524/how-to-convert-list-of-intable-strings-to-int And this method is working perfect! Thank you for your help! – PurplProto Nov 01 '15 at 21:47