Lambda for tuple sorting (python)

Hi there,

I’m trying to create the most efficient way of sorting a tuple. I have afunction called sort_deph(list) which is being passed a list.

The type of list I’ll be receiving looks like so: [(x1,y1,r1,d1),(x2,y2,r2,d2)…]

I have a rather strange need to sort this in a particular way. I need to sort the full list by the d value in the tuples but if there are any ties then I have to resort to r values. This is what I’ve got:

def sortfunct(a, b):
    # The values are coming into the function as tuples, what I've done is
    # instantly determine if there is a tie between them and reset the vaules
    # of a and b to what need to be logically checked for sorting purposes.
    # It returns -1, 0, 1 respectively to get the sorting done properly.
    a = (a(2), a(3))[a(3) == b(3)]
    b = (b(2), b(3))[a(3) == b(3)]
    if a > b:
        return -1
    elif a == b:
        return 0
        return 1


I haven’t tested that code, it’s just off the top of my head. What I’d REALLY like to do though realise it can potentially be dirtier (but more efficient) is to use lambda. The only problem is I don’t know how to use it properly and the tutorials/help docs don’t really explain how to do conditionals in it. Here is my best guess:

list.sort(lambda a, b: ( << do it with d >>, << do it with r >>) [a(3) == b(3)])

So yeah, erm I read something about shortcircuiting but really have no idea how to use it :-/ I’m probably going to get screamed at for doing it this way but I say … why not? If I can just figure it out now…

I don’t seem to be getting any good reaction on this…I have some more information that might help others…help me, heh.

Here’s the code I’m using:

# My first try:
list.sort(lambda a, b: (cmp(a(3), b(3)), cmp(a(2), b(2))) [a(3) == b(3)])

# My second try:
list.sort(lambda a, b: (cmp(a[3], b[3]), cmp(a[2], b[2])) [a[3] == b[3]])

So basically what’s happening here is that the lambda is receiving the two values from the sort function, which I’m then using a special conditional expression to determine if there is indeed a tie between the d value. If the tie true then perform a basic cmp (which returns -1, 0 and 1 as it should) on the value that I want it to.

My question though is, I was under the impression that accessing a tuple you had to use () instead of . Whenever I tried this I’d get “tuple is not callable” errors. I changed the brackets to which I thought was for accessing a list.

So I’m happy it works BUT I’m wondering why it’s working as a list. Does passing the function change its type or something?

Is this still a viable solution? Help? :-p please?

Use for accessing a list or a tuple. I think you are confusing this with the syntax for creating a list or tuple. They are created using different syntax, but accessed the same.

To create a list:

mylist = [1,2,3]

To create a tuple:

mytuple = (1,2,3)

Both are accessed using the operator

>>> mylist[0]
>>> 1
>>> mytuple[2]
>>> 3

Using mytuple(0) tries to treat the tuple object as a function and call it with argument 0, which won’t work since the tuple isn’t callable.

Hope that clears things up a bit.

Ahhhhhh. Yeah I thought the syntax for creating would be enforced for accessing it. But yeah what you’re saying makes complete sense. Great!

My next question is…according to my requirements of sorting list in the first post, would my method above work properly? I’m yet to test it with my code (need to finish other parts) but conceptually I think it works at least…

My next question is, do you think this would be more efficient than creating a separate function and have it called each time? The Python manual and most of the information on sort that I find seem to claim that using lambda makes doing these tasks more efficient.

What are your thoughts on that?

Thanks for your time! :wink:

Yes, I think it will work. You can always test such things with dummy data in a test script or the interactive console… python’s nice and easy like that.

I’d stick with lambdas - if the Python manual says that lambdas are more efficient, it’s probably right. It also makes the code neater and saves you having to think up names for these tiny functions. :slight_smile: