How to compare and sort several values

Hi all,

Simple Python question: how would you compare and sort different values in a script? I intend to use it in a racing game position system by first getting the distance travelled by each car (by doing a calculation distance = speed x time) and then comparing the resulting values (so the highest would be 1st etc).

Cheers

Paul

ok, well let’s assume you have a list.
Lists are easy to sort, as they have the .sort() feature
if your list was:
list = [1.4,65.3,0.7,2]
list = list.sort()
would sort it for you.
if you wanted to reverse the sort, use list.sort(reverse=True)
or, if you wanted to sort a dictionary, of other iterables, use sorted()

Thanks for the info agoose! If I do the following I get NONE in the DOS window:



list = [2,4,5,1,8,19]

list = list.sort()

print (list)


What gives?

sorry, don’t put:
list = list.sort()
instead:
list.sort()

Whooo! It works! Out of interest, how would you sort lists in a script that has two defined lists? I assumed that Python would need to be told which list to sort, but the list.sort() command doesnt ‘equal’ something (this is my brain trying to get Python!)

Cheers for your help

Paul

I’m not quite sure what you’re asking?

It was this:



list = [2,4,5,1,8,19]

list2 = [67,98,56]

list.sort()

print (list)


I wondered what would happen if another list was introduced- how would list2 be sorted? Is it possible to sort list2 high to low, whilst list 1 low to high?

For “list2” use another sort function which has reverse enabled :slight_smile:

If you are sorting non comparable objects such as game objects it can be a little more tricky since they do not compare to each other like numbers do. If you wanted to sort a list like:

cars = [car1, car2, car3, car4]

Where car1-car4 are game objects you will have to use the key keyword argument which allows you to specify what exactly should be used for the comparison. For instance, the following will sort game objects based on a property ‘distance_travelled’ that they contain

def get_distance(game_object):
    return game_object['distance_travelled']

cars = [car1, car2, car3, car4]
cars.sort(key=get_distance)

The key argument must be a callable (i.e, a function), each element will be passed to it and it should return a comparable value (numbers).

This can be done, and often is done, inline using the lambda keyword:

cars = [..]
cars.sort(key=lambda game_object: game_object['distance_travelled'])

If You want to sort list2 do list2.sort()

Cool, thanks for the advice everyone!

I was thinking of getting round the problem of game objects as lists by having each car have a ‘distance travelled’ property that was called up by the global dictionary command (somehow!) and inserted into an empty list (list = [] I take it and appended?). This way, the list function is sorting numerical data that is pumped directly to on-screen text objects via properties (to update a position system).

I assume its possible to pick out a number (or item) on a list- e.g. for a list = [1,2,3] selecting 2?

Items are numbered from 0, so first item in list is list[0], second item is list[1] …

OK, super thick question, how would I define the cars in Andrew-101s example? The set up I imagined would be a value in all car objects being beamed into this script which is attached to a leaderboard, with eight text fields fed by list[0], list[1] etc (thanks LaH!)

cars[0] has traveled shortest, cars[3] longest.

Sorry, I meant if I run the code snippet from Andrew-101 I would get a ‘car1’ not defined- how do I define an object not connected to the script?

import bge
scene = bge.logic.getCurrentScene()
objects = scene.objects
car1 = objects["car1"]
car2 = objects["car2"]
car3 = objects["car3"]
cars = [car1,car2,car3]

any function that acknowledges game objects, e.g ray.hitObject or near.hitObject creates a reference to a game object
so you can add it to a variable or list
car1 = near.hitObject

As agoose said, you can get the object from the scene’s object list, or from different sensors that return objects with different functions (like the Near sensor).

Thanks guys, I will get this one day!

Right, I’ve got everything working- the three cubes in the attached example each have a value that is (or can be) adjusted either directly or via script, and are sorted by the scoreboard.

I’ve set up three text objects with empty properties that will indicate what car is first: but how do I get a value from the sorted list in the scoreboard script into the First/Second/Third properties of the text objects?

Attachments

sort_by_distance.blend (369 KB)

In text_driver_first.py for example


import bge

GL = bge.logic

cont = GL.getCurrentController()

own = cont.owner
own['First'] = GL.globalDict["First"]
own.text = str(own["First"])

Then in Sorting_Cars


import bge

scene = bge.logic.getCurrentScene()

objects = scene.objects

car1 = objects["car1"]

car2 = objects["car2"]

car3 = objects["car3"]

def get_distance(game_object):
   return game_object['distance_travelled']

cars = [car1, car2, car3]

cars.sort(key=get_distance)

bge.logic.globalDict["First"] = cars[0]     # First Place
bge.logic.globalDict["Second"] = cars[1]    # Second
bge.logic.globalDict["Third"] = cars[2]     # Third

print (cars)

Then change the other place texts to = the other globalDicts
If you add


GL = bge.logic

to your sorting_cars script itll be easier to remember how useful globaldict variables are, its what I always do