Page 1 of 1

Sorting items in dictionary

Posted: Sat Jan 25, 2014 6:02 pm
by arawra
I have a dictionary which contains a steamid, which is storing other dictionaries for attributes of a player. I am trying to sort these values to create a leader board, but am not getting the results I expect (sometimes, they're not displayed in order).

The specific attribute which should be sorted by is entered into the form. Values you could use to test are "fighter, cleric, wizard, rogue". Fighter seems to work flawlessly, but the issue I notice is with "cleric". Test page: http://thinkplace.tk/dnd/kills.py

Image

http://pastebin.com/3Gj1tYpn

Syntax: Select all

import cgi, cgitb
import pickle, os
cgitb.enable()
print 'Content-Type: text/html\n'
print '<html><body>Class Leaderboards<p>'

myForm = '<form method="get" action="kills.py">    Enter a Class to get people with the highest levels:<p>    <input type="text" name="Class"><input type="submit" value="Submit"></form>'

form = cgi.FieldStorage()
Class = form.getfirst('Class', 'fighter')
Class = cgi.escape(Class)

playerdata = {}
filename = 'playerdict.txt'
dndpath = './'
dndpath = dndpath + filename
if os.path.isfile(dndpath):
file_users = open(dndpath, 'rb')
try:
playerdata = pickle.load(file_users)
except:
pass
file_users.close()
else:
print 'Couldn\'t find file %s'%dndpath

myList = []
tempData = playerdata.copy()
currentPlayer = 0

print myForm

sortClass = Class.lower()
for z in range(10):
start = 0
for x,y in tempData.iteritems():
if sortClass in tempData[x]:
if start == 0:
currentPlayer = x
start = 1
if tempData[currentPlayer][sortClass] < tempData[x][sortClass]:
currentPlayer = x
myList.append(currentPlayer)
if currentPlayer in tempData:
del tempData[currentPlayer]

for x in myList:
if x in playerdata:
if sortClass in playerdata[x]:
print 'Name: %s | Level: %s
'%(playerdata[x]['name'], playerdata[x][sortClass])
else:
print '%s not found'%x


print "</body></html>"

Posted: Sat Jan 25, 2014 11:04 pm
by satoon101
I haven't looked through all your code, but I did test using the other classes as well on that page. The thing I notice is that it is sorting by the first number in the level. So, since 1 is less than 3, 17 is shown lower than 3. If you look at "wizard", you will see this as well. 1 is less than 2, so 15 is less than 2. 11 is less than 15, and then 1 is the overall lowest. This could very well be due to you storing level values as strings instead of integers. I can best show this using IDLE:

Syntax: Select all

>>> 17 > 2
True
>>> '17' > '2'
False


Also, I would think you might want to look into the built-in sorted function:

Syntax: Select all

sorted_players = sorted(playerdata, key=lambda player: playerdata[player][sortClass], reverse=True)
This will return a list of players in the order of their level on the specified sortClass. Again, though, if you have string values for the levels instead of integers, you will still encounter this issue as shown above.

Satoon

Posted: Sun Jan 26, 2014 12:24 am
by arawra
Yeah, the original database was written with keygroups, and I converted it to a dictionary. Thanks for the heads up.

Posted: Sun Jan 26, 2014 4:33 am
by Omega_K2
Dictionaries do not store order. They are unsorted. Look at OrderedDict if you need dict to store order itself.

Though you can still create a sorted list form a dictionaries keys or values. (sorted will return a sorted list of keys)